How can I pass a mat4 type shape to a custom shader (SCNProgram) in Swift?
I am trying to install a single mat4 that I want to use in a custom shader program in SceneKit on iOS (Xcode 6 beta 6). And I am trying to do this 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 ( https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html , Constants Pointers section), I understand that we can pass an array to a function which takes an UnsafePointer argument.
Then I tried to pass UnsafePointer directly 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 glUniformMatrix4fv prototype is exactly like this: func glUniformMatrix4fv(location: GLint, count: GLsizei, transpose: GLboolean, value: UnsafePointer<GLfloat>)
Any idea what I am doing wrong? How are we supposed to skip mat4 as a uniform if we are using a custom shader?
Note1: I first tried to use SCNMatrix4 for myMatrix, but got the error "SCNMatrix4 does not convert to UnsafePointer".
Note2: I was thinking about using GLKMatrix4, but this type is not recognized in Swift.
source to share
I have found that compiler error messages can provide more misdirection than help in determining how to call the C API. My troubleshooting technique was to declare each parameter as a local variable and see which one gets the red flag. In this case, it is not the last parameter to cause problems, it is GLboolean
.
let aTranspose = GLboolean(needToBeTransposed)
// Cannot invoke 'init' with an argument of type 'Bool'
It turns out GLboolean is defined like this:
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)
}
source to share