2017-07-02 5 views
1

Ich bin neu in Metal und ich bin verwirrt ...Second-Pass-Rendering in Metall - ist das so einfach?

Ich habe eine Reihe von Vertices, die ich aus einer Master-Textur "Tiling". Ich benutze sowohl einen Vertex-Shader als auch einen Fragment-Sampling-Shader, um dies zu tun.

Ich wollte den ersten Zeichnungsdurchlauf mit einem zusätzlichen Zeichnungsdurchlauf mit einer anderen Textur überlagern. Ich war total gestresst über Load/Store-Aktionen und so. Ach, nein - unten ist das, was ich in meiner Renderschleife in Swift gemacht habe. Ich sollte sagen, dass die Menge des Zeichnens in der Auflage weniger als 5% von der im ersten Durchlauf auslöscht.

Das funktioniert. Ist es wirklich so einfach?

Ich habe nur dieses nagende Gefühl, dass ich etwas vermisse. Andererseits habe ich vielleicht den falschen Eindruck gehabt, dass man in einer Render-Schleife nur eine Chance bekommt, sagen wir, um den Vertex-Puffer des Render-Encoders zu setzen.

let renderEncoder : MTLRenderCommandEncoder = (commandBuffer?.makeRenderCommandEncoder(descriptor: renderPassDescriptor!))! 
 
renderEncoder.label = "MyRenderEncoder" 
 

 
renderEncoder.setViewport(MTLViewport.init(originX: 0.0, originY: 0.0, width: Double(self.drawableSize.width), height: Double(self.drawableSize.height), znear: -1.0, zfar: 1.0)) 
 
renderEncoder.setRenderPipelineState(self.pipelineState) 
 

 
// draw main content 
 
let vertices = ... 
 
let vCount = vertices?.count 
 
let vSize = vCount!*MemoryLayout.size(ofValue: vertices?[0]) 
 
let mBuff = self.device!.makeBuffer(bytes: vertices!, length: vSize, options: []) 
 
renderEncoder.setVertexBuffer(mBuff, offset: 0, at: 0) 
 
renderEncoder.setVertexBytes(&self.viewportSize, length: MemoryLayout.size(ofValue: self.viewportSize), at: 1) 
 
renderEncoder.setFragmentTexture(inputTexture, at: 0) 
 
renderEncoder.drawPrimitives(type: MTLPrimitiveType.triangle, vertexStart: 0, vertexCount: vCount!) 
 

 
// draw overlaying content 
 
let vertices2 = ... 
 
let vCount2 = vertices2?.count 
 
let vSize2 = vCount2!*MemoryLayout.size(ofValue: vertices2?[0]) 
 
let mBuff2 = self.device!.makeBuffer(bytes: vertices2!, length: vSize2, options: []) 
 
renderEncoder.setVertexBuffer(mBuff2, offset: 0, at: 0) 
 
renderEncoder.setVertexBytes(&self.viewportSize, length: MemoryLayout.size(ofValue: self.viewportSize), at: 1) 
 
renderEncoder.setFragmentTexture(inputTexture2, at: 0) 
 
renderEncoder.drawPrimitives(type: MTLPrimitiveType.triangle, vertexStart: 0, vertexCount: vCount2!) 
 

 
// done drawing 
 
renderEncoder.endEncoding() 
 
commandBuffer?.present(view.currentDrawable!) 
 
commandBuffer?.commit()

Antwort

3

Es ist nicht wirklich klar, welche über Sie waren besorgt Teil, aber, ja, das funktioniert. Sie können die Eigenschaften eines Render-Befehls-Encoders ändern, für den es an einem beliebigen Punkt eine "set" -Methode gibt, und weitere Zeichnungen ausführen. Sie sind nicht beschränkt auf eine einzige Zeichnung pro Encoder, noch einmal eine einzige Zeichnungskonfiguration. Die einzigen Dinge, die für die Lebensdauer des Render-Befehlscodierers behoben werden, sind die Eigenschaften, die durch den Render-Pass-Deskriptor beschrieben werden, den Sie zum Erstellen verwenden.

Sie können sogar ändern, welcher Render-Pipeline-Status verwendet wird. Denken Sie jedoch daran, dass der Render-Pass-Deskriptor fest ist und die Pixel-Formate des Render-Pipeline-Zustands den Attachment-Texturen des Render-Pass-Deskriptors entsprechen müssen.

Natürlich, wenn Sie müssen, können Sie mehrere Befehlsgeber verwenden und es ist wirklich nicht schwer, die Lade- und Speicheraktionen einzurichten.

Verwandte Themen