gpt4 book ai didi

metal - MTLVertexAttributeDescriptor是否必要?为什么需要它们?

转载 作者:行者123 更新时间:2023-12-04 01:46:17 27 4
gpt4 key购买 nike

我一直在学习iOS / OSX的Metal,并且从Ray Wenderlich tutorial开始。本教程工作正常,但没有提及MTLVertexAttributeDescriptors

现在,我在开发自己的应用程序时,出现了一些奇怪的故障,并且想知道我不使用MTLVertexAttributeDescriptors的事实是否与问题有关。

他们有什么区别?我已经能够制作具有不同顶点结构的各种着色器,而我什至都不知道这些东西。

我知道您使用它们来描述用于着色器的顶点组件的布局。例如,着色器可能会将这种结构用于顶点,并将在下面的函数的顶点描述符中对其进行设置。

typedef struct
{
float3 position [[attribute(T_VertexAttributePosition)]];
float2 texCoord [[attribute(T_VertexAttributeTexcoord)]];
} Vertex;

class func buildMetalVertexDescriptor() -> MTLVertexDescriptor {

let mtlVertexDescriptor = MTLVertexDescriptor()

mtlVertexDescriptor.attributes[T_VertexAttribute.position.rawValue].format = MTLVertexFormat.float3
mtlVertexDescriptor.attributes[T_VertexAttribute.position.rawValue].offset = 0
mtlVertexDescriptor.attributes[T_VertexAttribute.position.rawValue].bufferIndex = T_BufferIndex.meshPositions.rawValue

mtlVertexDescriptor.attributes[T_VertexAttribute.texcoord.rawValue].format = MTLVertexFormat.float2
mtlVertexDescriptor.attributes[T_VertexAttribute.texcoord.rawValue].offset = 0
mtlVertexDescriptor.attributes[T_VertexAttribute.texcoord.rawValue].bufferIndex = T_BufferIndex.meshGenerics.rawValue

mtlVertexDescriptor.layouts[T_BufferIndex.meshPositions.rawValue].stride = 12
mtlVertexDescriptor.layouts[T_BufferIndex.meshPositions.rawValue].stepRate = 1
mtlVertexDescriptor.layouts[T_BufferIndex.meshPositions.rawValue].stepFunction = MTLVertexStepFunction.perVertex

mtlVertexDescriptor.layouts[T_BufferIndex.meshGenerics.rawValue].stride = 8
mtlVertexDescriptor.layouts[T_BufferIndex.meshGenerics.rawValue].stepRate = 1
mtlVertexDescriptor.layouts[T_BufferIndex.meshGenerics.rawValue].stepFunction = MTLVertexStepFunction.perVertex

return mtlVertexDescriptor
}


但是即使没有 MTLVertexDescriptor设置,着色器也已经可以访问顶点缓冲区和数组中顶点的 position / texCoord分量。仅通过设置顶点缓冲区,着色器即可访问所有组件。那么描述符有什么用呢?

最佳答案

当然,有多种处理方法。顶点描述符仅用于其中之一。

例如,顶点函数可以这样声明:

vertex MyVertexOut vertex_func(device const float3 *positions [[buffer(0)]],
device const float2 *texCoords [[buffer(1)]],
uint vid [[vertex_id]])
{
// use positions[vid] and texCoords[vid] to fill in and return a MyVertexOut structure
}


这表明顶点属性应在单独的缓冲区中提供,每个缓冲区都具有特定的布局。

您也可以这样做:

struct MyVertexIn
{
float3 position;
float2 texCoord;
};
vertex MyVertexOut vertex_func(device const MyVertexIn *vertexes [[buffer(0)]],
uint vid [[vertex_id]])
{
// use vertexes[vid].position and vertexes[vid].texCoord to fill in and return a MyVertexOut structure
}


这就要求在与 MyVertexIn布局匹配的结构的单个缓冲区中提供顶点属性。

以上都不要求或不使用顶点描述符。完全无关紧要。

但是,您也可以这样做:

struct MyVertexIn
{
float3 position [[attribute(0)]];
float2 texCoord [[attribute(1)]];
};
vertex MyVertexOut vertex_func(MyVertexIn vertex [[stage_in]])
{
// use vertex.position and vertex.texCoord to fill in and return a MyVertexOut structure
}


请注意 attribute(n)stage_in属性的使用。这并不决定如何提供顶点属性。相反,顶点描述符描述了从一个或多个缓冲区到顶点属性的映射。该映射还可以执行转换和扩展。例如,上面的着色器代码指定 position字段是 float3,但是缓冲区可能包含(并描述为包含) half3值(或其他各种类型),Metal将自动进行转换。

相同的着色器可与不同的顶点描述符一起使用,因此,顶点属性在缓冲区中的分布不同。这为不同的场景提供了灵活性,其中一些将顶点属性分离到不同的缓冲区中(类似于我给出的第一个示例),而另一些将它们插入同一缓冲区中(与第二个示例类似)。等等。

如果不需要这种灵活性和额外的抽象级别,则不需要处理顶点描述符。他们在那里是那些确实需要他们的人。

关于metal - MTLVertexAttributeDescriptor是否必要?为什么需要它们?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47044663/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com