【问题标题】:SCNProgram – How to pass a uniform of type "mat4" to a custom shader?SCNProgram – 如何将“mat4”类型的制服传递给自定义着色器?
【发布时间】:2014-10-19 00:35:37
【问题描述】:

我正在尝试设置一个统一的 mat4,我想在 iOS 上的 SceneKit(Xcode 6 beta 6)中的自定义着色器程序中使用它。我正在尝试在 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&lt;GLfloat&gt;)。但是,根据此处的文档 (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&lt;GLfloat&gt;)'

然而,glUniformMatrix4fv的原型正是这样的:

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

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

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

注意2:我想过使用GLKMatrix4,但是Swift不识别这种类型。

【问题讨论】:

    标签: ios opengl-es swift scenekit


    【解决方案1】:

    我发现在弄清楚如何调用 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)
    }
    

    【讨论】:

    • 谢谢内特。有用。我只是不确定是否理解。为什么GLboolean(false) 不起作用但GLboolean(false ? 1 : 0) 起作用?它们都产生一个 GLboolean。
    • 布尔值在 C 中通常表示为 0(零)表示假,非零(通常为 1)表示真。然后,这些整数值可以在需要布尔表达式的任何地方使用,例如在 if 语句中。 (出于这个原因,Swift 将 GLboolean 导入为 Int8 的别名)。将其与 Swift 原生的 Bool 类型进行比较,后者是具有一些内部价值的 struct。这种差异就是为什么您不能简单地使用 Swift 原生 Bool 值初始化 GLboolean,而是可以使用 1 或 0。
    猜你喜欢
    • 1970-01-01
    • 2016-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多