Metal render with 2 pipelines, the second object o

2019-05-23 08:32发布

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)

    }
}    

标签: metal
1条回答
成全新的幸福
2楼-- · 2019-05-23 09:19

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...

查看更多
登录 后发表回答