Instancing | raywenderlich.com


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/1258241-3d-graphics-with-metal/lessons/32
1 Like

Thank you for your instructions. It’s very helpful for me.

For Instance class, my code dosen’t works well. While making 100 transforms in init() of Instance class, it makes all same transforms. So I modified code with below. Why did this happen?

class Instance: Model {
var transforms: [Transform] = Transform
var instanceCount: Int
var instanceBuffer: MTLBuffer

init(name: String, instanceCount: Int = 1) {

// transforms = [Transform](repeatElement(Transform(), count: instanceCount))
for _ in 0 …< instanceCount {
let t = Transform()
transforms.append(t)
}

    self.instanceCount = instanceCount
    instanceBuffer = Renderer.device.makeBuffer(length: instanceCount * MemoryLayout<Instances>.stride, options: [])!
    
    super.init(name: name)
}

override func render(commandEncoder: MTLRenderCommandEncoder, submesh: Submesh) {
    var pointer = instanceBuffer.contents().bindMemory(to: Instances.self, capacity: instanceCount)
    for transform in transforms {
        pointer.pointee.modelMatrix = transform.matrix
        pointer = pointer.advanced(by: 1)
    }
    commandEncoder.setVertexBuffer(instanceBuffer, offset: 0, index: 20)
    commandEncoder.setRenderPipelineState(submesh.instancedPipelineState)
    
    let mtkSubmesh = submesh.mtkSubmesh

    commandEncoder.drawIndexedPrimitives(type: .triangle, indexCount: mtkSubmesh.indexCount, indexType: mtkSubmesh.indexType, indexBuffer: mtkSubmesh.indexBuffer.buffer, indexBufferOffset: mtkSubmesh.indexBuffer.offset, instanceCount: instanceCount)
}

}

Hi - did the final project sample work for you?

transforms = [Transform](repeatElement(Transform(), count: instanceCount))

That is in the project that I run and it works for me. I am using Xcode 11.4.1 on a 2019 MacBook Pro with a Vega 20 GPU.

Your alternative

for _ in 0 …< instanceCount {
   let t = Transform()
   transforms.append(t)
}

is just as good though.