[英]“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.