我正在尝试从场景中添加多个对象,从Xcode 9的Metal Game App模板开始。
我已经根据这个答案尽可能少地修改了默认游戏模板,以渲染多个对象:https://stackoverflow.com/a/37424817/518169
我的问题是没有出现第二个对象。添加打印行显示缓冲区在CPU上更新,但使用GPU帧捕获我可以看到GPU上没有。实际上发生的是第二个立方体的状态用于两个绘制调用。使用// left cube
var modelMatrix = matrix4x4_translation(-3, 0, 0)
var viewMatrix = matrix4x4_translation(0.0, 0.0, -8.0)
uniforms[0].modelViewMatrix = simd_mul(viewMatrix, modelMatrix)
print(uniforms[0])
for submesh in mesh.submeshes {
renderEncoder.drawIndexedPrimitives(type: submesh.primitiveType, indexCount: submesh.indexCount, indexType: submesh.indexType, indexBuffer: submesh.indexBuffer.buffer, indexBufferOffset: submesh.indexBuffer.offset)
}
// right cube
modelMatrix = matrix4x4_translation(3, 0, 0)
viewMatrix = matrix4x4_translation(0.0, 0.0, -8.0)
uniforms[0].modelViewMatrix = simd_mul(viewMatrix, modelMatrix)
print(uniforms[0])
for submesh in mesh.submeshes {
renderEncoder.drawIndexedPrimitives(type: submesh.primitiveType, indexCount: submesh.indexCount, indexType: submesh.indexType, indexBuffer: submesh.indexBuffer.buffer, indexBufferOffset: submesh.indexBuffer.offset)
}
时,这不会发生。
最小案例:Xcode 9 /使用Metal的新跨平台游戏,并将drawIndexedPrimitives部分替换为:
let alignedUniformsSize = (MemoryLayout<Uniforms>.size & ~0xFF) + 0x100
let maxBuffersInFlight = 3
class Renderer: NSObject, MTKViewDelegate {
var dynamicUniformBuffer: MTLBuffer
let inFlightSemaphore = DispatchSemaphore(value: maxBuffersInFlight)
var uniformBufferOffset = 0
var uniformBufferIndex = 0
var uniforms: UnsafeMutablePointer<Uniforms>
init?(metalKitView: MTKView) {
let uniformBufferSize = alignedUniformsSize * maxBuffersInFlight
guard let buffer = self.device.makeBuffer(length: uniformBufferSize, options: [MTLResourceOptions.storageModeShared]) else { return nil }
dynamicUniformBuffer = buffer
uniforms = UnsafeMutableRawPointer(dynamicUniformBuffer.contents()).bindMemory(to: Uniforms.self, capacity: 1)
}
private func updateDynamicBufferState() {
uniformBufferIndex = (uniformBufferIndex + 1) % maxBuffersInFlight
uniformBufferOffset = alignedUniformsSize * uniformBufferIndex
uniforms = UnsafeMutableRawPointer(dynamicUniformBuffer.contents() + uniformBufferOffset).bindMemory(to: Uniforms.self, capacity: 1)
}
func draw(in view: MTKView) {
_ = inFlightSemaphore.wait(timeout: DispatchTime.distantFuture)
if let commandBuffer = commandQueue.makeCommandBuffer() {
let semaphore = inFlightSemaphore
commandBuffer.addCompletedHandler { (_) -> Swift.Void in semaphore.signal()}
updateDynamicBufferState()
updateGameState()
if let renderPassDescriptor = view.currentRenderPassDescriptor, let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) {
renderEncoder.setCullMode(.back)
renderEncoder.setRenderPipelineState(pipelineState)
renderEncoder.setVertexBuffer(dynamicUniformBuffer, offset: uniformBufferOffset, index: BufferIndex.uniforms.rawValue)
renderEncoder.setFragmentBuffer(dynamicUniformBuffer, offset: uniformBufferOffset, index: BufferIndex.uniforms.rawValue)
for (index, element) in mesh.vertexDescriptor.layouts.enumerated() {
guard let layout = element as? MDLVertexBufferLayout else {return}
if layout.stride != 0 {
let buffer = mesh.vertexBuffers[index]
renderEncoder.setVertexBuffer(buffer.buffer, offset: buffer.offset, index: index)
}
}
renderEncoder.setFragmentTexture(colorMap, index: TextureIndex.color.rawValue)
// left cube
var modelMatrix = matrix4x4_translation(-3, 0, 0)
var viewMatrix = matrix4x4_translation(0.0, 0.0, -8.0)
uniforms[0].modelViewMatrix = simd_mul(viewMatrix, modelMatrix)
print(uniforms[0])
for submesh in mesh.submeshes {
renderEncoder.drawIndexedPrimitives(type: submesh.primitiveType, indexCount: submesh.indexCount, indexType: submesh.indexType, indexBuffer: submesh.indexBuffer.buffer, indexBufferOffset: submesh.indexBuffer.offset)
}
// right cube
modelMatrix = matrix4x4_translation(3, 0, 0)
viewMatrix = matrix4x4_translation(0.0, 0.0, -8.0)
uniforms[0].modelViewMatrix = simd_mul(viewMatrix, modelMatrix)
print(uniforms[0])
for submesh in mesh.submeshes {
renderEncoder.drawIndexedPrimitives(type: submesh.primitiveType, indexCount: submesh.indexCount, indexType: submesh.indexType, indexBuffer: submesh.indexBuffer.buffer, indexBufferOffset: submesh.indexBuffer.offset)
}
renderEncoder.endEncoding()
if let drawable = view.currentDrawable {
commandBuffer.present(drawable)
}
}
commandBuffer.commit()
}
}
}
完整文件的框架如下所示(供将来参考):
{{1}}