我正在将一个结构体数组传递给我的Metal着色器顶点函数。这个结构体看起来像这样:
struct Vertex {
var x,y,z: Float // position data
var r,g,b,a: Float // color data
var s,t: Float // texture coordinates
var nX,nY,nZ: Float // normal
func floatBuffer() -> [Float] {
return [x,y,z,r,g,b,a,s,t,nX,nY,nZ]
}
};
floatBuffer函数用于将顶点组合成一个大的Floats数组。我可以使用结构体定义将其传递到我的着色器函数中,该结构体使用"packed"数据类型,如下所示:
struct VertexIn {
packed_float3 position;
packed_float4 color;
packed_float2 texCoord;
packed_float3 normal;
};
vertex VertexOut basic_vertex(
const device VertexIn* vertex_array [[ buffer(0) ]],
.
.
.
这个方案是可行的。不过,我想知道如何使用MTLVertexAttributeDescriptors和相关语法来完成同样的事情。目前,我得到的是变形的多边形,可能是由于float3和packed_float3之间的字节对齐差异所致?
这是我现在尝试定义它并得到垃圾多边形的方式。我收到了一个错误,指出“packed_float3”不适用于属性,因此我正在努力弄清楚如何让常规的float3、float4等工作。
struct VertexIn {
float3 position [[attribute(RayVertexAttributePosition)]];
float4 color [[attribute(RayVertexAttributeColor)]];
float2 texCoord [[attribute(RayVertexAttributeTexCoord)]];
float3 normal [[attribute(RayVertexAttributeNormal)]];
};
class func buildMetalVertexDescriptor() -> MTLVertexDescriptor {
let mtlVertexDescriptor = MTLVertexDescriptor()
var offset = 0
mtlVertexDescriptor.attributes[RayVertexAttribute.position.rawValue].format = MTLVertexFormat.float3
mtlVertexDescriptor.attributes[RayVertexAttribute.position.rawValue].offset = offset
mtlVertexDescriptor.attributes[RayVertexAttribute.position.rawValue].bufferIndex = RayBufferIndex.positions.rawValue
offset += 3*MemoryLayout<Float>.stride
mtlVertexDescriptor.attributes[RayVertexAttribute.color.rawValue].format = MTLVertexFormat.float4
mtlVertexDescriptor.attributes[RayVertexAttribute.color.rawValue].offset = offset
mtlVertexDescriptor.attributes[RayVertexAttribute.color.rawValue].bufferIndex = RayBufferIndex.positions.rawValue
offset += MemoryLayout<float4>.stride
mtlVertexDescriptor.attributes[RayVertexAttribute.texCoord.rawValue].format = MTLVertexFormat.float2
mtlVertexDescriptor.attributes[RayVertexAttribute.texCoord.rawValue].offset = offset
mtlVertexDescriptor.attributes[RayVertexAttribute.texCoord.rawValue].bufferIndex = RayBufferIndex.positions.rawValue
offset += MemoryLayout<float2>.stride
mtlVertexDescriptor.attributes[RayVertexAttribute.normal.rawValue].format = MTLVertexFormat.float3
mtlVertexDescriptor.attributes[RayVertexAttribute.normal.rawValue].offset = offset
mtlVertexDescriptor.attributes[RayVertexAttribute.normal.rawValue].bufferIndex = RayBufferIndex.positions.rawValue
offset += 3*MemoryLayout<Float>.stride
print("stride \(offset)")
mtlVertexDescriptor.layouts[RayBufferIndex.positions.rawValue].stride = offset
mtlVertexDescriptor.layouts[RayBufferIndex.positions.rawValue].stepRate = 1
mtlVertexDescriptor.layouts[RayBufferIndex.positions.rawValue].stepFunction = MTLVertexStepFunction.perVertex
return mtlVertexDescriptor
}
注意,我将第一个属性指定为float3,但是我指定了3个浮点数的偏移量,而不是通常使用的4个float3。但显然这还不够。我想知道如何设置MTLVertexDescriptor和着色器结构与属性,以处理来自我的结构体的“压缩”数据?
非常感谢。
float4
数据的示例。这种不对齐是由于在float2
之后紧密打包,但这与您的float3
情况没有区别。所以,正如Warren所说,它应该可以工作。 - Ken Thomases