Reputation: 524
The SCNShadable Reference states that a shade modifier in SceneKit
may contain custom global functions. However, since the update to Xcode 7
this option seems not to work anymore. Even the Apple example from the reference page does not compile anymore. According to the error message the custom functions are simply absent from the resulting OpenGL
shader source code, which is generated by SceneKit
.
Does anybody know how this new limitation (or bug?) can be worked around? Maybe an additional pragma is needed?
The problem can be seen in the first example given on the SCNShadable Reference under "Writing a Shader Modifier Snippet".
To see the error, simply create a new Xcode
"game" project and paste the following code at the end of GameViewController.viewDidLoad()
:
let fragmentShader =
"// 1. Custom variable declarations (optional)\n" +
"// For Metal, a pragma directive and one custom variable on each line:\n" +
"#pragma arguments\n" +
"float intensity;\n" +
"// For OpenGL, a separate uniform declaration for each custom variable\n" +
"uniform float intensity;\n" +
"\n" +
"// 2. Custom global functions (optional)\n" +
"vec2 sincos(float t) { return vec2(sin(t), cos(t)); }\n" +
"\n" +
"// 3. Pragma directives (optional)\n" +
"#pragma transparent\n" +
"#pragma body\n" +
"\n" +
"// 4. Code snippet\n" +
"_geometry.position.xy = sincos(u_time);\n"
"_geometry.position.z = intensity;\n"
if let material = ship.childNodes.first?.geometry?.materials.first {
material.shaderModifiers = [SCNShaderModifierEntryPointGeometry: fragmentShader]
}
Running the program gives the following error, stating that the custom identifier sincos
is undefined:
SceneKit: error, failed to link program: ERROR: 0:191: Invalid call of undeclared identifier 'sincos'
In the error message you can also see the program which SceneKit has generated for the shade modifier. It contains everything but the definition of sincos
which has somehow been filtered out.
Upvotes: 4
Views: 744
Reputation: 4064
You should not use "#pragma arguments" for a shader modifier written in GLSL (the documentation in the SCNShadable.h header specifies that it is for metal shaders only). So this will work:
uniform float intensity;
// Custom global functions (optional)
vec2 sincos(float t) { return vec2(sin(t), cos(t)); }
// Pragma directives (optional)
#pragma transparent
#pragma body
// Code snippet
_geometry.position.xy = sincos(u_time);
_geometry.position.z = intensity;
Upvotes: 5