morph208
morph208

Reputation: 110

Why SceneKit on iOS 8 cannot compile my custom shaders?

I created a new project based on the Game template with SceneKit as game technology and Swift for the language. And I tried to use a custom shader. Here is the setup code:

var material = SCNMaterial()
var program = SCNProgram()

// Read the vertex shader file and set its content as our vertex shader
if let vertexShaderPath = NSBundle.mainBundle().pathForResource("VertexShader", ofType:"vsh") {
    let vertexShaderAsAString = NSString(contentsOfFile: vertexShaderPath, encoding: NSUTF8StringEncoding, error: nil)
    program.vertexShader = vertexShaderAsAString
}

// Read the fragment shader file and set its content as our fragment shader
if let fragmentShaderPath = NSBundle.mainBundle().pathForResource("FragmentShader", ofType:"fsh") {
    let fragmentShaderAsAString = NSString(contentsOfFile: fragmentShaderPath, encoding: NSUTF8StringEncoding, error: nil)
    program.fragmentShader = fragmentShaderAsAString
}

// Give a meaning to variables used in the shaders
program.setSemantic(SCNGeometrySourceSemanticVertex, forSymbol: "a_position", options: nil)
program.setSemantic(SCNModelViewProjectionTransform, forSymbol: "u_viewProjectionTransformMatrix", options: nil)

material.program = program

// retrieve the ship node
let ship = scene.rootNode.childNodeWithName("shipMesh", recursively: true)
ship.geometry.firstMaterial = material

The code of my vertex shader:

#version 300 es

uniform mat4 u_viewProjectionTransformMatrix;
in vec4 a_position;
out vec4 outPosition;

void main() {
   outPosition = u_viewProjectionTransformMatrix * a_position;
}

And the code of my fragment shader:

#version 300 es

out vec4 outColor;

void main() {
    outColor = vec4(1.0, 0.0, 0.0, 1.0)
}

Pretty simple, right? But when I execute this code, I get the following error:

SceneKit: error, failed to link program: ERROR: 0:1: '' :  version '300' is not supported
ERROR: 0:1: '' : syntax error: #version

What did I do wrong? For your information, #version 200 es yields the same result so it does not seem to be related to the version of OpenGL per se.

Upvotes: 2

Views: 2324

Answers (1)

rickster
rickster

Reputation: 126117

SceneKit uses an OpenGL ES 2.0 context by default.

If you want to use ES3 features (like #version 300 es shaders) you can create an EAGLContext object specifying OpenGL ES 3.0 as the API version, then assign it to your view's eaglContext property.

However, not all of SceneKit's renderer features support ES3, so you'll have to experiment to see if what you want to render works. Also keep in mind that ES3 requires an A7 GPU -- to support iPhone 4s/5/5c, iPad 4 and earlier, iPad mini (non-retina) and iPod touch, you'll need an ES2 rendering path.

If you're sticking to ES2 shaders, you're seeing an error because there's no #version 200 es. ES2 shaders use #version 100, or no #version directive at all (in which case 100 is implicit).

Upvotes: 5

Related Questions