Draw Indexed Primitives (Metal Part 9)

z4gon
z4gon

Defining the indices array for the meshes, to remove duplicate vertices from the vertices array. Sending the indices array as an index buffer to the GPU, to describe how to render the primitive triangles.

Source Code

See Project in GitHub 👩‍💻

References


Table of Content


Mesh Indices

The Mesh now also sets an array of indices to go along the array of vertices.

This allows to eliminate duplicates and optimize memory utilization.

Picture

Image Source 🔗

1class Mesh { 2 public var vertices: [Vertex]! = [] 3 public var indices: [UInt32]! = [] 4 5 init(){ 6 createMesh() 7 } 8 9 func createMesh() {} 10}
1class QuadMesh : Mesh{ 2 override func createMesh() { 3 vertices = [ 4 Vertex(position: float3( 0.5, 0.5,0), color: float4(1,0,0,1)), //Top Right 5 Vertex(position: float3(-0.5, 0.5,0), color: float4(0,1,0,1)), //Top Left 6 Vertex(position: float3(-0.5,-0.5,0), color: float4(0,0,1,1)), //Bottom Left 7 Vertex(position: float3( 0.5,-0.5,0), color: float4(1,0,1,1)) //Bottom Right 8 ] 9 10 indices = [ 11 0,1,2, 12 0,2,3 13 ] 14 } 15}

Index Buffer

The Mesh Renderer will create another MTLBuffer to send these indexes to the GPU.

1class MeshRenderer : Component, Renderable { 2 3 ... 4 5 private var _vertexBuffer: MTLBuffer! 6 private var _indexBuffer: MTLBuffer! 7 8 ... 9 10 init(mesh: Mesh) { 11 _mesh = mesh 12 13 _vertexBuffer = Engine.device.makeBuffer(bytes: _mesh.vertices, length: Vertex.stride * _mesh.vertices.count, options: []) 14 15 if(_mesh.indices.count > 0){ 16 _indexBuffer = Engine.device.makeBuffer(bytes: _mesh.indices, length: UInt32.stride * _mesh.indices.count, options: []) 17 } 18 } 19}

Draw Indexed Primitive

The Mesh Renderer will draw the primitives by sending the indices as instructions on how to interpret the vertices to draw the triangles.

1func doRender(renderCommandEncoder: MTLRenderCommandEncoder) { 2 3 ... 4 5 if(_mesh.indices.count > 0){ 6 renderCommandEncoder.drawIndexedPrimitives( 7 type: MTLPrimitiveType.triangle, 8 indexCount: _mesh.indices.count, 9 indexType: MTLIndexType.uint32, 10 indexBuffer: _indexBuffer, 11 indexBufferOffset: 0, 12 instanceCount: 1 // for now, might change in the future 13 ) 14 } else { 15 renderCommandEncoder.drawPrimitives( 16 type: MTLPrimitiveType.triangle, 17 vertexStart: 0, 18 vertexCount: _mesh.vertices.count 19 ) 20 } 21}