I am developing a Metal macOS app that displays my own 3D models and some other 3D model.obj I import through the Model I/O
. I am getting some conflict between my own vertexDescriptor
and the vertexDescriptor
embedded into the model.obj.
I have found a patch to the trouble creating a brand new MTLRenderPipelineState
per each model.obj imported (with its own vertexDescriptor
), but I think this is not the proper way to do. I cannot imagine that I have to create a brand new MTLRenderPipelineState
per each model (read each "different vertexDescriptor
") imported. Any clue to work with a unique MTLRenderPipelineState
for all the models in the app?
Here's a sample case. I create my own vertexDescriptor
Buffer 0:
stepFunction = MTLVertexStepFunctionPerVertex
stride = 64
Attribute 0: // Position
offset = 0
format = MTLAttributeFormatFloat3
Attribute 1: // Normal
offset = 16
format = MTLAttributeFormatFloat3
Attribute 2: // Texture Coords
offset = 32
format = MTLAttributeFormatFloat2
Attribute 3: // Vertex Color
offset = 48
format = MTLAttributeFormatFloat4
and I use it to configure my MTLRenderPipelineState
accordingly with my vertex shader MyVertexShader's argument
struct VertexIn
{
float4 position[[attribute(0)]];
float4 normal[[attribute(1)]];
float2 uvTex[[attribute(2)]];
float4 color[[attribute(3)]];
};
Everything works well with the models I create myself using always the same VertexIn
structure. But when I import a model.obj file with Model I/O
and automatically get this vertexDescriptor
Buffer 0:
stepFunction = MTLVertexStepFunctionPerVertex
stride = 32
Attribute 0: // Position
offset = 0
format = MTLAttributeFormatFloat3
Attribute 1: // Normal
offset = 12
format = MTLAttributeFormatFloat3
Attribute 2: // Texture Coords
offset = 24
format = MTLAttributeFormatFloat2
the stride
is 32 (mine above is 64), the 4th attribute
(color) is missed, so the model.obj looks jerky on the MTKView
.
So, I created a brand new MTLRenderPipelineState
only to draw this model.obj using the model.obj's vertexDescriptor
and my own vertex shader function MyVertexShader. Well, I got this error
*Error: Vertex attribute color(3) is missing from the vertex descriptor*
So I added the 4th attribute
color to the model.obj vertexDescriptor
if(objVertexDescriptor.attributes[3].format == MTLVertexFormatInvalid)
{
// add the color attribute to the model.obj vertexDescriptor
objVertexDescriptor.attributes[3].format = MTLVertexFormatFloat4;
objVertexDescriptor.attributes[3].offset = sizeof(simd_float3) + sizeof(simd_float3) + sizeof(simd_float3);
objVertexDescriptor.attributes[3].bufferIndex = 0;
}
then I created a brand new MTLRenderPipelineState
with this objVertexDescriptor
and my own vertex shader function MyVertexShader, and the model.obj finally looked well on the MTKView
.
I feel that what I'm doing it's just a bad patch to this trouble and I think there should be a better and reusable way to solve the conflict hopefully using the same MTLRenderPipelineState
for all the models. I can't accept I should create a new pipeline per each model the user will import. Any idea?