I have 2 objects, one is with texture, the other one is without texture. I use 2 shaders and I use 2 render pipelines to draw the 2 objects. the 2 object are drawn fine...but when the second obejct is drawn ...it overlaps the first object, so only the second object is on screen... don't know where goes wrong...Maybe because the pipeline is not used right, in the last part of the draw() function. the model draws properly first, but when the sky is drew, the model disappeared...Please help me,,,Thanks Here is my code:
class PanoViewController: GameViewController {
//sky
var depthStencilState: MTLDepthStencilState! = nil
var vertexBufferSky: MTLBuffer! = nil
var uniformBufferSky: MTLBuffer! = nil
var depthTextureSky: MTLTexture! = nil
var diffuseTextureSky: MTLTexture! = nil
var samplerStateSky: MTLSamplerState! = nil
//model
var depthStencilStateModel: MTLDepthStencilState! = nil
var vertexBufferModel: MTLBuffer! = nil
var normalBufferModel: MTLBuffer! = nil
var colorBufferModel: MTLBuffer! = nil
var uniformBufferModel: MTLBuffer! = nil
override func buildPipeline() {
//Model
let library = device!.newDefaultLibrary()!
//pipeline descriptor
// buildPipelinForSky(library)
// buildPipelineForModel(library)
//pipeline
do {
pipelineSky = try device!.newRenderPipelineStateWithDescriptor(buildPipelinForSky(library))
pipelineModel = try device!.newRenderPipelineStateWithDescriptor(buildPipelineForModel(library))
} catch {
print("error with device.newRenderPipelineStateWithDescriptor")
}
let depthStencilDescriptor = MTLDepthStencilDescriptor()
depthStencilDescriptor.depthCompareFunction = .Less
depthStencilDescriptor.depthWriteEnabled = true
depthStencilState = device!.newDepthStencilStateWithDescriptor(depthStencilDescriptor)
commandQueue = device!.newCommandQueue()
}
func buildPipelineForModel(library: MTLLibrary) -> MTLRenderPipelineDescriptor {
let pipeLineDesc = MTLRenderPipelineDescriptor()
let vertexFunctionModel = library.newFunctionWithName("vertex_ply")
let fragmentFunctionModel = library.newFunctionWithName("fragment_ply")
let vertexDescriptorModel = MTLVertexDescriptor()
vertexDescriptorModel.attributes[0].offset = 0
vertexDescriptorModel.attributes[0].format = .Float4
vertexDescriptorModel.attributes[0].bufferIndex = 0
vertexDescriptorModel.layouts[0].stepFunction = .PerVertex
vertexDescriptorModel.layouts[0].stride = sizeof(Float) * 4
pipeLineDesc.vertexFunction = vertexFunctionModel
pipeLineDesc.vertexDescriptor = vertexDescriptorModel
pipeLineDesc.fragmentFunction = fragmentFunctionModel
pipeLineDesc.colorAttachments[0].pixelFormat = .BGRA8Unorm
return pipeLineDesc
}
func buildPipelinForSky(library: MTLLibrary ) -> MTLRenderPipelineDescriptor{
let pipeLineDesc = MTLRenderPipelineDescriptor()
let vertexFunctionSky = library.newFunctionWithName("vertex_sky")
let fragmentFunctionSky = library.newFunctionWithName("fragment_sky")
let vertexDescriptorSky = MTLVertexDescriptor()
vertexDescriptorSky.attributes[0].offset = 0
vertexDescriptorSky.attributes[0].format = .Float4
vertexDescriptorSky.attributes[0].bufferIndex = 0
vertexDescriptorSky.attributes[1].offset = sizeof(Float32) * 4
vertexDescriptorSky.attributes[1].format = .Float4
vertexDescriptorSky.attributes[1].bufferIndex = 0
vertexDescriptorSky.attributes[2].offset = sizeof(Float32) * 8
vertexDescriptorSky.attributes[2].format = .Float2
vertexDescriptorSky.attributes[2].bufferIndex = 0
vertexDescriptorSky.layouts[0].stepFunction = .PerVertex
vertexDescriptorSky.layouts[0].stride = sizeof(Vertex)
pipeLineDesc.vertexFunction = vertexFunctionSky
pipeLineDesc.vertexDescriptor = vertexDescriptorSky
pipeLineDesc.fragmentFunction = fragmentFunctionSky
pipeLineDesc.colorAttachments[0].pixelFormat = .BGRA8Unorm
pipeLineDesc.depthAttachmentPixelFormat = .Depth32Float
let samplerDescriptorSky = MTLSamplerDescriptor()
samplerDescriptorSky.minFilter = .Nearest
samplerDescriptorSky.magFilter = .Linear
samplerStateSky = device!.newSamplerStateWithDescriptor(samplerDescriptorSky)
return pipeLineDesc
}
override func buildResources() {
//Model
(vertexBufferModel,normalBufferModel,colorBufferModel) = PointCloud.model(device!)
uniformBufferModel = device!.newBufferWithLength(sizeof(M4f) * 2, options: .OptionCPUCacheModeDefault)
//Sky
vertexBufferSky = SkySphere.sphere(device!)
uniformBufferSky = device!.newBufferWithLength(sizeof(M4f) * 2, options: .OptionCPUCacheModeDefault)
diffuseTextureSky = self.textureForImage(UIImage(named: "bluemarble")!, device: device!)
}
override func resize() {
//Model
super.resize()
//Sky
let layerSizeSky = metalLayer.drawableSize
let depthTextureDescriptorSky = MTLTextureDescriptor.texture2DDescriptorWithPixelFormat(.Depth32Float,
width: Int(layerSizeSky.width),
height: Int(layerSizeSky.height),
mipmapped: false)
depthTextureSky = device!.newTextureWithDescriptor(depthTextureDescriptorSky)
}
override func draw() {
dispatch_semaphore_wait(inflightSemaphore, DISPATCH_TIME_FOREVER)
if let drawable = metalLayer.nextDrawable()
{
var modelMatrixTransSky = M4f()
var modelMatrixRotSky = M4f()
var modelMatrixScaleSky = M4f()
modelMatrixTransSky = translate(0, y: 0, z: 0)
modelMatrixRotSky = rotate(90, r: V3f(1,0,0)) * modelMatrixRotSky
modelMatrixScaleSky = scaling(10, y: 10, z: 10)
let modelMatrixSky = modelMatrixTransSky * modelMatrixRotSky * modelMatrixScaleSky
var viewMatrixSky = M4f()
viewMatrixSky = myCamera.setLookAt(viewMatrixSky)
let modelViewMatrixSky = viewMatrixSky * modelMatrixSky
let aspect = Float32(metalLayer.drawableSize.width) / Float32(metalLayer.drawableSize.height)
let kFOVY:Float = 85.0
let projectionMatrix = perspective_fov(kFOVY, aspect: aspect, near: 0.1, far: 180.0)
let matricesSky = [projectionMatrix, modelViewMatrixSky]
memcpy(uniformBufferSky.contents(), matricesSky, Int(sizeof(M4f) * 2))
//Model
var modelMatrixTransModel = M4f()
var modelMatrixRotModel = M4f()
var modelMatrixScaleModel = M4f()
modelMatrixTransModel = translate(0, y: 0, z: 0)
modelMatrixRotModel = rotate(0, r: V3f(1,0,0))
modelMatrixScaleModel = scaling(10, y: 10, z: 10)
let modelMatrixModel = modelMatrixTransModel * modelMatrixRotModel * modelMatrixScaleModel
var viewMatrixModel = M4f()
viewMatrixModel = myCamera.setLookAt(viewMatrixModel)
let modelViewMatrixModel = viewMatrixModel * modelMatrixModel
let matricesModel = [projectionMatrix, modelViewMatrixModel]
memcpy(uniformBufferModel.contents(), matricesModel, Int(sizeof(M4f) * 2))
//command buffer
let commandBuffer = commandQueue.commandBuffer()
commandBuffer.addCompletedHandler{ [weak self] commandBuffer in
if let strongSelf = self {
dispatch_semaphore_signal(strongSelf.inflightSemaphore)
}
return
}
//model
var passDescriptor = MTLRenderPassDescriptor()
passDescriptor = passDescrForModel(drawable,passDescriptor: passDescriptor)
var commandEncoder = commandBuffer.renderCommandEncoderWithDescriptor(passDescriptor)
commandEncoder.pushDebugGroup("model pass")
commandEncoder.label = "model buffer"
pointCloudDraw(commandEncoder)
commandEncoder.endEncoding()
commandEncoder.popDebugGroup()
passDescriptor = passDescrForSky(drawable,passDescriptor: passDescriptor)
commandEncoder = commandBuffer.renderCommandEncoderWithDescriptor(passDescriptor)
commandEncoder.pushDebugGroup("sky pass")
commandEncoder.label = "sky buffer"
skyDraw(commandEncoder)
commandEncoder.popDebugGroup()
commandEncoder.endEncoding()
commandBuffer.presentDrawable(drawable)
// bufferIndex matches the current semaphore controled frame index to ensure writing occurs at the correct region in the vertex buffer
bufferIndex = (bufferIndex + 1) % MaxBuffers
commandBuffer.commit()
}
}
func passDescrForModel(drawable: CAMetalDrawable, passDescriptor:MTLRenderPassDescriptor) -> MTLRenderPassDescriptor{
passDescriptor.colorAttachments[0].texture = drawable.texture
// passDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.5, 0.5, 0.5, 1)
passDescriptor.colorAttachments[0].loadAction = .Clear
passDescriptor.colorAttachments[0].storeAction = .Store
return passDescriptor
}
func passDescrForSky(drawable: CAMetalDrawable, passDescriptor:MTLRenderPassDescriptor) -> MTLRenderPassDescriptor{
passDescriptor.colorAttachments[0].texture = drawable.texture
// passDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.5, 0.5, 0.5, 1)
passDescriptor.colorAttachments[0].loadAction = .Clear
passDescriptor.colorAttachments[0].storeAction = .Store
passDescriptor.depthAttachment.texture = depthTextureSky
passDescriptor.depthAttachment.clearDepth = 1
passDescriptor.depthAttachment.loadAction = .Clear
passDescriptor.depthAttachment.storeAction = .DontCare
return passDescriptor
}
func pointCloudDraw(commandencodeModel: MTLRenderCommandEncoder){
commandencodeModel.setRenderPipelineState(pipelineModel)
commandencodeModel.setDepthStencilState(depthStencilState)
commandencodeModel.setFrontFacingWinding(.CounterClockwise)
commandencodeModel.setCullMode(.Back)
commandencodeModel.setVertexBuffer(vertexBufferModel, offset:0, atIndex:0)
commandencodeModel.setVertexBuffer(normalBufferModel, offset:0, atIndex:1)
commandencodeModel.setVertexBuffer(colorBufferModel, offset:0, atIndex:2)
commandencodeModel.setVertexBuffer(uniformBufferModel, offset:0, atIndex:3)
commandencodeModel.setFragmentBuffer(uniformBufferModel, offset: 0, atIndex: 0)
commandencodeModel.drawPrimitives(.Point, vertexStart: 0, vertexCount: vertextCountModel)
}
func skyDraw(commandencodeSky: MTLRenderCommandEncoder) {
commandencodeSky.setRenderPipelineState(pipelineSky)
commandencodeSky.setDepthStencilState(depthStencilState)
commandencodeSky.setFrontFacingWinding(.CounterClockwise)
commandencodeSky.setCullMode(.Back)
commandencodeSky.setVertexBuffer(vertexBufferSky, offset:0, atIndex:0)
commandencodeSky.setVertexBuffer(uniformBufferSky, offset:0, atIndex:1)
commandencodeSky.setFragmentTexture(diffuseTextureSky, atIndex: 0)
commandencodeSky.setFragmentSamplerState(samplerStateSky, atIndex: 0)
commandencodeSky.drawPrimitives(.Triangle, vertexStart: 0, vertexCount: vertexCountSky)
}
}
Change the passDescrForSky function
passDescriptor.colorAttachments[0].loadAction = .Load
Then the 2 objects are all shows up...Something happen to the position...the first one needs to be adjusted...