Draw Indexed Primitives (Metal Part 9)
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
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.
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}