SCNProgram - 如何将“mat4”类型的制服传递给自定义着色器?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SCNProgram - 如何将“mat4”类型的制服传递给自定义着色器?相关的知识,希望对你有一定的参考价值。

我正在尝试设置一个统一的mat4,我想在ios(Xcode 6 beta 6)的SceneKit中的自定义着色器程序中使用。而我正试图在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)
}

使用此代码,我有以下编译错误:Cannot invoke 'init' with an argument list of type (GLint, GLsizei, GLboolean, Array<GLfloat>)。但是,从这里的文档(section "Constant pointers")我的理解是,我们可以将一个数组传递给一个以UnsafePointer作为参数的函数。

然后我尝试通过执行以下操作直接传递UnsafePointer:

let testPtr: UnsafePointer<GLfloat> = nil
glUniformMatrix4fv(GLint(location), GLsizei(numberOfMatrices), GLboolean(needToBeTransposed), testPtr)

我得到了错误Cannot invoke 'init' with an argument list of type '(GLint, GLsizei, GLboolean, UnsafePointer<GLfloat>)'

但是,glUniformMatrix4fv的原型正是如此:

func glUniformMatrix4fv(location: GLint, count: GLsizei, transpose: GLboolean, value: UnsafePointer<GLfloat>)

我知道我做错了什么?如果我们使用自定义着色器,我们如何将mat4作为制服传递?

注1:我首先尝试将SCNMatrix4用于myMatrix,但我收到错误“SCNMatrix4无法转换为UnsafePointer”。

注2:我想过使用GLKMatrix4但是在Swift中无法识别这种类型。

答案

我发现在确定如何调用C API时,编译器的错误消息可能提供更多误导而不是帮助。我的故障排除技术是将每个参数声明为局部变量,并查看哪个获取红色标志。在这种情况下,它不是导致问题的最后一个参数,它是GLboolean

let aTranspose = GLboolean(needToBeTransposed)
// Cannot invoke 'init' with an argument of type 'Bool'

结果GLboolean是这样定义的:

typealias GLboolean = UInt8

所以这是我们需要的代码:

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)
}

以上是关于SCNProgram - 如何将“mat4”类型的制服传递给自定义着色器?的主要内容,如果未能解决你的问题,请参考以下文章

如何将mat4数组作为制服传递

使用金属顶点和片段着色器将 MTLTexture 传递给 SCNProgram

如何从 glm::mat4 读取值

为啥金属着色器渐变作为 SCNProgram 应用于 SceneKit 节点比作为 MTKView 更轻?

将 glm.mat4 从 Python 传回 C++ (glm::mat4)

glm::mat4 构造函数如何工作?