Captain Fim
Captain Fim

Reputation: 524

SceneKit: Shademodifier ignores custom global function in Xcode 7

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

Answers (1)

Toyos
Toyos

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

Related Questions