簡體   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