繁体   English   中英

尝试将制服传递给金属着色器时,“SceneKit:错误,缺少缓冲区[-1/2]”

[英]“SceneKit: error, missing buffer [-1/2]” when trying to pass uniforms to a metal shader

我已经将SCNProgram附加到SceneKit的几何体上,我试图将制服传递给片段着色器。 在我的简单代码片段中,我只是将输出颜色作为一个统一体传递给片段着色器,它将其作为输出值返回。

我已经测试了着色器并且它们工作,从某种意义上说,我可以成功地旋转顶点着色器中的对象,或者在片段着色器中绘制不同颜色的对象等等......但问题是当我通过时制服。 这是我的片段着色器:

struct Uniforms
{
    float4 color;
};


fragment float4 myFragment(MyVertexOutput in [[ stage_in ]],
                           constant Uniforms& uniforms [[buffer(2)]])
{
    return uniforms.color;
}

这就是我尝试在SceneKit + Swift代码中传递制服的方法:

SCNTransaction.begin()
cube.geometry?.setValue(NSValue(SCNVector4:SCNVector4(0.0,1.0,0.0,1.0)), forKey: "uniforms.color")
SCNTransaction.commit()

但我的对象(它是一个立方体)甚至没有绘制(它是黑色的),我得到这个错误:

2016-04-01 01:00:34.485 Shaded Cube [30266:12687154] SceneKit:错误,缺少缓冲区[-1/0]

编辑我试图按照@lock的建议,但我仍然得到同样的错误。 这是完整的项目存储库: https//github.com/ramy89/Shaded-Cube.git

你的着色器代码看起来很好,你穿着制服的方式接近于工作。

着色器制服的名称必须与setValue使用的名称相匹配。 在这种情况下,您的Metal变量名称是uniforms ,您在setValue使用的值是uniforms.color 这些不匹配,因此您看到的错误。 建议更改swift代码,只需在setValue调用中使用uniforms即可。

接下来,您需要确保传入的数据,因为setValue的值在Metal和Swift中都是相同的。 SCNVector4是四个64位双精度(CGFloats)的结构,而Metal的float4是四个32位浮点数的结构。 文档似乎表明您可以将SCNVector作为NSValue传递,但我从来没有让它工作。

在你的swift代码中,我创建了一个包含你想要传入的制服的结构。在vector_float4结构上没有很多文档,但它与Metal float4结构相匹配,因为它是四个32位浮点数。

struct Uniforms {
    var color:vector_float4
}

将此值作为NSData传递给setValue函数。

let myColor = vector_float4(0,1,0,1)
var myUniforms = Uniforms(color:myColor)
var myData = NSData(bytes:&myUniforms, length:sizeof(Uniforms))
cube.geometry?.setValue(myData, forKey: "uniforms")

我不确定你是否需要SCNTransaction电话,我过去不需要它们,而且它们可能SCNTransaction

更新

在查看Ramy的代码之后,当应用于几何体时,似乎存在setValue和SCNPrograms的问题。 我不能告诉你为什么,但是将自定义着色器设置为材料似乎可以解决这个问题,例如;

func makeShaders()
{
    let program = SCNProgram()
    program.vertexFunctionName = "myVertex"
    program.fragmentFunctionName = "myFragment"
    //cube.geometry?.program = program
    cube.geometry?.firstMaterial?.program = program

    var uniforms = Uniforms(color: vector_float4(0.0,1.0,0.0,1.0))
    let uniformsData = NSData(bytes: &uniforms, length: sizeof(Uniforms))
    //cube.geometry?.setValue(uniformsData, forKey: "uniforms")
    cube.geometry?.firstMaterial?.setValue(uniformsData, forKey: "uniforms")
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM