Reputation: 110
I'm trying to set a uniform mat4 that I want to use in a custom shader program in SceneKit on iOS (Xcode 6 beta 6). And I'm trying to do that in Swift.
let myMatrix: Array<GLfloat> = [1, 0, 0 , 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1]
var material = SCNMaterial()
var program = SCNProgram()
// setup of vertex/fragment shader goes here
program.vertexShader = //...
program.fragmentShader = //...
material.program = program
// I want to initialize the variable declared as "uniform mat4 u_matrix" in the vertex shader with "myMatrix"
material.handleBindingOfSymbol("u_matrix") {
programID, location, renderedNode, renderer in
let numberOfMatrices = 1
let needToBeTransposed = false
glUniformMatrix4fv(GLint(location), GLsizei(numberOfMatrices), GLboolean(needToBeTransposed), myMatrix)
}
Using this code, I have the following compilation error: Cannot invoke 'init' with an argument list of type (GLint, GLsizei, GLboolean, Array<GLfloat>)
. However, from this documentation here (section "Constant pointers") it is my understanding that we can pass an array to a function that takes an UnsafePointer as argument.
I then tried to directly pass an UnsafePointer by doing the following:
let testPtr: UnsafePointer<GLfloat> = nil
glUniformMatrix4fv(GLint(location), GLsizei(numberOfMatrices), GLboolean(needToBeTransposed), testPtr)
And I got the error Cannot invoke 'init' with an argument list of type '(GLint, GLsizei, GLboolean, UnsafePointer<GLfloat>)'
However, the prototype of glUniformMatrix4fv is exactly that:
func glUniformMatrix4fv(location: GLint, count: GLsizei, transpose: GLboolean, value: UnsafePointer<GLfloat>)
Any idea of what I'm doing wrong? How are we supposed to pass a mat4 as an uniform if we use a custom shader?
Note1: I first attempted to use a SCNMatrix4 for myMatrix but I got the error "SCNMatrix4 is not convertible to UnsafePointer".
Note2: I thought of using GLKMatrix4 but this type is not recognized in Swift.
Upvotes: 3
Views: 1864
Reputation: 93276
I've found the compiler's error messages can provide more misdirection than help when figuring out how to call C APIs. My troubleshooting technique has been to declare each parameter as a local variable and see which one gets the red flag. In this case, it's not the last parameter that's causing problems, it's the GLboolean
.
let aTranspose = GLboolean(needToBeTransposed)
// Cannot invoke 'init' with an argument of type 'Bool'
Turns out GLboolean is defined this way:
typealias GLboolean = UInt8
So this is the code we need:
material.handleBindingOfSymbol("u_matrix") {
programID, location, renderedNode, renderer in
let numberOfMatrices = 1
let needToBeTransposed = false
let aLoc = GLint(location)
let aCount = GLsizei(numberOfMatrices)
let aTranspose = GLboolean(needToBeTransposed ? 1 : 0)
glUniformMatrix4fv(aLoc, aCount, aTranspose, myMatrix)
}
Upvotes: 1