金属画2个不同的对象,仅显示一个 [英] Metal draw 2 different objects, only one is showing

查看:80
本文介绍了金属画2个不同的对象,仅显示一个的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用Metal渲染2个不同的对象...我有2个不同的着色器,不同的renderpipeline和命令缓冲区,passDescriptors,它们都是不同的.但是在屏幕上只有一个对象正在绘制,我没有不知道我哪里出了错....这是绘制函数:

I want to render 2 different objects with Metal...I have 2 different shaders, different renderpipeline, and command buffers, passDescriptors, they are all different..But there is only one object is drawing on the screen, I don't know where i went wrong.... Here is the draw function:

 dispatch_semaphore_wait(inflightSemaphore, DISPATCH_TIME_FOREVER)

            //Sky
            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))

                let commandBufferSky = commandQueue.commandBuffer()
                commandBufferSky.addCompletedHandler{ [weak self] commandBufferSky in
                    if let strongSelf = self {
                        dispatch_semaphore_signal(strongSelf.inflightSemaphore)
                    }
                    return
                }

                //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))

                let commandBufferModel = commandQueue.commandBuffer()
                commandBufferModel.addCompletedHandler{ [weak self] commandBufferModel in
                    if let strongSelf = self {
                        dispatch_semaphore_signal(strongSelf.inflightSemaphore)
                    }
                    return
                }

                //Sky
                let passDescriptorSky = MTLRenderPassDescriptor()
                passDescriptorSky.colorAttachments[0].texture = drawable.texture
                passDescriptorSky.colorAttachments[0].clearColor = MTLClearColorMake(0.05, 0.05, 0.05, 1)
                passDescriptorSky.colorAttachments[0].loadAction = .Clear
                passDescriptorSky.colorAttachments[0].storeAction = .Store

                passDescriptorSky.depthAttachment.texture = depthTextureSky
                passDescriptorSky.depthAttachment.clearDepth = 1
                passDescriptorSky.depthAttachment.loadAction = .Clear
                passDescriptorSky.depthAttachment.storeAction = .DontCare


                //Model
                let passDescriptorModel = MTLRenderPassDescriptor()
                passDescriptorModel.colorAttachments[0].texture = drawable.texture
                passDescriptorModel.colorAttachments[0].clearColor = MTLClearColorMake(0.5, 0.5, 0.5, 1)
                passDescriptorModel.colorAttachments[0].loadAction = .Clear
                passDescriptorModel.colorAttachments[0].storeAction = .Store

                //Sky
                let commandEncoderSky = commandBufferSky.renderCommandEncoderWithDescriptor(passDescriptorSky)
                let commandEncoderModel = commandBufferModel.renderCommandEncoderWithDescriptor(passDescriptorModel)

                commandEncoderSky.setRenderPipelineState(pipelineSky)
                commandEncoderSky.setDepthStencilState(depthStencilState)
                commandEncoderSky.setFrontFacingWinding(.CounterClockwise)
                commandEncoderSky.setCullMode(.Back)
                commandEncoderSky.setVertexBuffer(vertexBufferSky, offset:0, atIndex:0)
                commandEncoderSky.setVertexBuffer(uniformBufferSky, offset:0, atIndex:1)
                commandEncoderSky.setFragmentTexture(diffuseTextureSky, atIndex: 0)
                commandEncoderSky.setFragmentSamplerState(samplerStateSky, atIndex: 0)
                commandEncoderSky.drawPrimitives(.Triangle, vertexStart: 0, vertexCount: vertexCountSky)
                commandEncoderSky.endEncoding()
                commandBufferSky.presentDrawable(drawable)

                //Model
                commandEncoderModel.setRenderPipelineState(pipelineModel)
                commandEncoderModel.setDepthStencilState(depthStencilState)
                commandEncoderModel.setFrontFacingWinding(.CounterClockwise)
                commandEncoderModel.setCullMode(.Back)
                commandEncoderModel.setVertexBuffer(vertexBufferModel, offset:0, atIndex:0)
                commandEncoderModel.setVertexBuffer(normalBufferModel, offset:0, atIndex:1)
                commandEncoderModel.setVertexBuffer(colorBufferModel, offset:0, atIndex:2)
                commandEncoderModel.setVertexBuffer(uniformBufferModel, offset:0, atIndex:3)
                commandEncoderModel.setFragmentBuffer(uniformBufferModel, offset: 0, atIndex: 0)
                commandEncoderModel.drawPrimitives(.Point, vertexStart: 0, vertexCount: vertextCountModel)
                commandEncoderModel.endEncoding()
                commandBufferModel.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
                commandBufferSky.commit()

                bufferIndex = (bufferIndex + 1) % MaxBuffers
                commandBufferModel.commit()

            }

这是构建管道的功能:

//Model
        let library = device!.newDefaultLibrary()!

        let vertexFunctionModel = library.newFunctionWithName("vertex_ply")
        let fragmentFunctionModel = library.newFunctionWithName("fragment_ply")
        let vertexFunctionSky = library.newFunctionWithName("vertex_sky")
        let fragmentFunctionSky = library.newFunctionWithName("fragment_sky")

        //Model
        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

        //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)

        //Model
        let pipelineDescriptorModel = MTLRenderPipelineDescriptor()
        pipelineDescriptorModel.vertexFunction = vertexFunctionModel
        pipelineDescriptorModel.vertexDescriptor = vertexDescriptorModel
        pipelineDescriptorModel.fragmentFunction = fragmentFunctionModel
        pipelineDescriptorModel.colorAttachments[0].pixelFormat = .BGRA8Unorm

        //Sky
        let pipelineDescriptorSky = MTLRenderPipelineDescriptor()
        pipelineDescriptorSky.vertexFunction = vertexFunctionSky
        pipelineDescriptorSky.vertexDescriptor = vertexDescriptorSky
        pipelineDescriptorSky.fragmentFunction = fragmentFunctionSky
        pipelineDescriptorSky.colorAttachments[0].pixelFormat = .BGRA8Unorm
        pipelineDescriptorSky.depthAttachmentPixelFormat = .Depth32Float

        //Model
        do {
            pipelineModel = try device!.newRenderPipelineStateWithDescriptor(pipelineDescriptorModel)
        } catch {
            print("error with device.newRenderPipelineStateWithDescriptor")
        }

//        //Sky
        do {
            pipelineSky = try device!.newRenderPipelineStateWithDescriptor(pipelineDescriptorSky)
        } catch {
            print("error with device.newRenderPipelineStateWithDescriptor")
        }

        //Model
        let depthStencilDescriptor = MTLDepthStencilDescriptor()
        depthStencilDescriptor.depthCompareFunction = .Less
        depthStencilDescriptor.depthWriteEnabled = true
        depthStencilState = device!.newDepthStencilStateWithDescriptor(depthStencilDescriptor)
        commandQueue = device!.newCommandQueue()

        //Sky
        let samplerDescriptorSky = MTLSamplerDescriptor()
        samplerDescriptorSky.minFilter = .Nearest
        samplerDescriptorSky.magFilter = .Linear
        samplerStateSky = device!.newSamplerStateWithDescriptor(samplerDescriptorSky)

推荐答案

除非您要跨线程进行编码工作,否则只需要为每帧创建一个命令缓冲区.另外,除非您需要进行多次渲染(不仅是多次绘制调用,而且实际上需要在随后的渲染中从一次渲染中读取图像数据),否则每个命令缓冲区仅需要一个渲染命令编码器.

Unless you want to do encoding work across threads, you only need to create one command buffer per frame. Also, unless you need to perform rendering in multiple passes (not just multiple draw calls, actually reading image data back from one pass in a subsequent pass), you only need one render command encoder per command buffer.

在伪代码中,这是一帧的样子:

In pseudocode, here's what one frame looks like:

// semaphore wait
commandBuffer = commandQueue.makeCommandBuffer()!
commandBuffer.addCompletedHandler {
    // semaphore signal
}
commandEncoder = commandBuffer.makeRenderCommandEncoder()!
for obj in objects {
    commandEncoder.setRenderPipelineState(renderPipeline)
    commandEncoder.setVertexBuffer(...)
    // set other per-draw state on the encoder
    commandEncoder.drawPrimitives(...)
}
commandEncoder.endEncoding()
commandBuffer.presentDrawable(currentDrawable)
commandBuffer.commit()

这篇关于金属画2个不同的对象,仅显示一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆