简体   繁体   English

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

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

I've attached a SCNProgram to a SceneKit's geometry, and I'm trying to pass uniforms to the fragment shader. 我已经将SCNProgram附加到SceneKit的几何体上,我试图将制服传递给片段着色器。 In my simple code snippet I just pass the output color to the fragment shader as a uniform, which returns it as an output value. 在我的简单代码片段中,我只是将输出颜色作为一个统一体传递给片段着色器,它将其作为输出值返回。

I've already tested the shaders and they work, in the sense that I can succesfully rotate an object in the vertex shader, or draw an object in a different color in the fragment shader, etc... but the problem is when I pass the uniforms. 我已经测试了着色器并且它们工作,从某种意义上说,我可以成功地旋转顶点着色器中的对象,或者在片段着色器中绘制不同颜色的对象等等......但问题是当我通过时制服。 This is my fragment shader: 这是我的片段着色器:

struct Uniforms
{
    float4 color;
};


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

And this is how I try to pass the uniforms in my SceneKit+Swift code: 这就是我尝试在SceneKit + Swift代码中传递制服的方法:

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

But my object (it's a cube) is not even drawn (it's black), and I get this error: 但我的对象(它是一个立方体)甚至没有绘制(它是黑色的),我得到这个错误:

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

EDIT I tried to follow @lock's suggestions, but I'm still getting the same error. 编辑我试图按照@lock的建议,但我仍然得到同样的错误。 This is the full project repository: https://github.com/ramy89/Shaded-Cube.git 这是完整的项目存储库: https//github.com/ramy89/Shaded-Cube.git

Your shader code looks fine, and the way you're passing the uniform in is close to working. 你的着色器代码看起来很好,你穿着制服的方式接近于工作。

The name of the shader uniform must match that which is used in setValue . 着色器制服的名称必须与setValue使用的名称相匹配。 In this case your Metal variable name is uniforms and the value you use in setValue is uniforms.color . 在这种情况下,您的Metal变量名称是uniforms ,您在setValue使用的值是uniforms.color These don't match, hence the error you see. 这些不匹配,因此您看到的错误。 Suggest changing the swift code to simply use uniforms in the setValue call. 建议更改swift代码,只需在setValue调用中使用uniforms即可。

Next you need to ensure the data passed in as the value to setValue is the same in both Metal and Swift. 接下来,您需要确保传入的数据,因为setValue的值在Metal和Swift中都是相同的。 A SCNVector4 is a struct of four 64bit doubles (CGFloats), whereas Metal's float4 is a struct of four 32bit floats. SCNVector4是四个64位双精度(CGFloats)的结构,而Metal的float4是四个32位浮点数的结构。 The documentation seems to indicate you can pass in a SCNVector as a NSValue but I've never got it to work. 文档似乎表明您可以将SCNVector作为NSValue传递,但我从来没有让它工作。

In your swift code I'd create a struct to contain the uniforms you want to pass in. There's not a lot of documentation on the vector_float4 struct, but it matches the Metal float4 struct in that it is four 32bit floats. 在你的swift代码中,我创建了一个包含你想要传入的制服的结构。在vector_float4结构上没有很多文档,但它与Metal float4结构相匹配,因为它是四个32位浮点数。

struct Uniforms {
    var color:vector_float4
}

Pass this into the setValue function as NSData . 将此值作为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")

I'm not sure you need the SCNTransaction calls, I've not needed them in past and they could be costly performance wise. 我不确定你是否需要SCNTransaction电话,我过去不需要它们,而且它们可能SCNTransaction

update 更新

After looking at Ramy's code it seems there is an issue with setValue and SCNPrograms when applied to the geometry. 在查看Ramy的代码之后,当应用于几何体时,似乎存在setValue和SCNPrograms的问题。 I can't tell you why, but setting the custom shader to the material seems to fix this, eg; 我不能告诉你为什么,但是将自定义着色器设置为材料似乎可以解决这个问题,例如;

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.

相关问题 如何将纹理缓冲区数据传递给Shader with Metal? - How to pass texture buffer data to Shader with Metal? SceneKit金属深度缓冲区 - SceneKit Metal Depth Buffer SceneKit中的金属着色器勾勒出一个对象 - Metal shader in SceneKit to outline an object 使用 Metal 间接命令缓冲区时出错:“片段着色器不能与间接命令缓冲区一起使用” - Error when using Metal Indirect Command Buffer: "Fragment shader cannot be used with indirect command buffers" 将数字添加到数组值时,由于执行期间发生错误,命令缓冲区的Swift Metal Shader执行被中止 - Swift Metal Shader Execution of the command buffer was aborted due to an error during execution when adding a number to an array value 金属着色器在缓冲区中插值 - Metal shader interpolate values in buffer 如何定义具有动态缓冲区声明的金属着色器? - How define a metal shader with dynamic buffer declaration? iOS 14 解决方案中的 SceneKit Metal 着色器编译性能错误 - SceneKit Metal shader compilation performance bug in iOS 14 workaround ideas Xamarin OpenGL片段着色器使用制服时的行为异常 - Xamarin OpenGL fragment shader weird behaviour when working with uniforms 使用太多制服时着色器无法编译 - Shader fails to compile when using too many uniforms
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM