arrays - Scenekit 在将数组数据传递给 openGL 着色器中的统一数组时出现缓冲区大小错误

标签 arrays swift opengl-es shader scenekit

这是我用来在地板表面制作轨迹的表面着色器。

#pragma arguments
uniform vec2 trailPoints[5];
uniform float count;

#pragma body
float trailRadius = 10.0;

float x = _surface.diffuseTexcoord.x;
float x100 = float(x * 100);

float y = _surface.diffuseTexcoord.y;
float y100 = float(y * 100);

for (int i = 0; i < int(count); i++) {
    vec2 position = trailPoints[i];
    if ((x100 > position.x - trailRadius && x100 < position.x + trailRadius) && (y100 > position.y - trailRadius && y100 < position.y + trailRadius)) {
        _surface.diffuse.rgb = vec3(0.0, 10.0 ,0.0);
    }
}

这是我用来将矢量数据传递给表面着色器的快速辅助代码。

            if let geometry = self.floorNode.geometry {
                if let material = geometry.firstMaterial {

                    // this is the temporary data which I use to find the problem.
                    // this data will be dynamic later on.
                    let myValueArray:[float2] = [float2(x:80, y:80),float2(x:60, y:60),float2(x:40, y:40),float2(x:20, y:20),float2(x:0, y:0)]

                    // Passing array count to shader. There is no problem here.
                    var count = Float(myValueArray.count)
                    let countData = Data(buffer: UnsafeBufferPointer(start: &count, count: 1))
                    material.setValue(countData, forKey: "count")

                    // and here is the problem start. 
                    // myValueArray converted to data with its size.
                    let valueArrayData = Data(buffer: UnsafeBufferPointer(start: myValueArray, count: myValueArray.count))
                    material.setValue(valueArrayData, forKey: "trailPoints")                    
                }                
            }

当我构建和运行项目时,发生以下错误,并且没有数据传递到着色器中的“trailPoints”。

错误:参数 trailPoints:NSData 和缓冲区大小 40 之间不匹配!= 8

当我在将数组转换为数据时将数组计数更改为 1 时,

let valueArrayData = Data(buffer: UnsafeBufferPointer(start: myValueArray, count: 1))

错误消失了,但只有数组的第一个成员会传递给着色器。

所以,问题是,

如何将所有数组成员传递给着色器?

最佳答案

我想,这个问题的答案是这样的:

我最近意识到,the OpenGl ES 2.0 only allow the following array definitions :

float myValue[3];
myValue[0] = 1.0;
myValue[1] = 2.0;
myValue[2] = 3.0;

但据我所知,通过以下方式使用 SCNShaderModifierEntryPoint 是不可能做到这一点的。

material.setValue (1.0, forKey: "myValue[0]")
material.setValue (2.0, forKey: "myValue[1]")
material.setValue (3.0, forKey: "myValue[2]")

最后我找到了一种使用 SCNProgram handleBinding 方法将数组传递给片段着色器的方法。

let myValue:[Float] = [1.0, 2.0, 3.0]
material.handleBinding(ofSymbol:"myValue", handler: { (programId:UInt32, location:UInt32, node:SCNNode?, renderer:SCNRenderer) in
       for (index, v) in myValue.enumerated() {
            var v1 = v
            let aLoc = glGetUniformLocation(programId, String(format: "myValue[%i]", index))
            glUniform1fv(GLint(aLoc), 1, &v1)
       }
 })

但是,SCNProgram 完全摆脱了默认的 swift 着色器程序并使用你的。 swift 的默认着色器程序非常复杂,并且会根据您的位置做很多事情。

default vertex shader of swift

default fragment shader of swift

因此使用 SCNProgram 仅将数组传递给着色器可能不是一个好主意。

还有一件有趣的事,SCNProgram does not work on SCNFloor geometry.

关于arrays - Scenekit 在将数组数据传递给 openGL 着色器中的统一数组时出现缓冲区大小错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41713965/

相关文章:

javascript - 创建 Javascript 数组的不同方法

swift - Swift 协议(protocol)可以是单例的吗?

android - 如何在 OpenGL ES 中的纹理上添加一些像素

Android Matrix.multiplyMV 没有通过翻译改变我的结果

c# - Windows形成不同的类,试图改变textbox.text

javascript - 插入数字字符串

c - 我如何将结构的成员复制到 C 中的 double 组中?

Swift 关闭 UITextView 键盘

Swift:在另一个 switch 语句中重构 switch 语句

iphone - CADisplayLink OpenGL 渲染破坏了 UIScrollView 行为