这是我用来在地板表面上制作痕迹的表面着色器。
#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))
错误消失但只有数组的第一个成员将传递给着色器。
所以,问题是,
如何将所有数组成员传递给着色器?
答案 0 :(得分: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仅将数组传递给着色器可能不是一个好主意。