金属绘制一个对象与纹理一个对象没有纹理

时间:2016-05-25 15:50:29

标签: metal

我想用Metal渲染2个不同的物体......一个是纹理,另一个是没有纹理。我有2个不同的着色器,2个不同的顶点描述符,这意味着我应该使用2个不同的渲染管道? ..屏幕上只有一个对象绘图(带纹理的模型)正确,另一个是错误的,我不知道我哪里出错了......这是代码:

     override func buildPipeline() {
        //Model
        let library = device!.newDefaultLibrary()!
        let pipelineDescriptor = MTLRenderPipelineDescriptor()

        buildPipelinForSky(pipelineDescriptor, library: library)
        buildPipelineForModel(pipelineDescriptor, library: library)

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



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

        }

    func buildPipelineForModel(pipeLineDesc:MTLRenderPipelineDescriptor, library: MTLLibrary) -> 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(pipeLineDesc:MTLRenderPipelineDescriptor, library: MTLLibrary ) -> 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.depthAttachmentPixelFormat = .Depth32Float

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

        return pipeLineDesc

    }

    override func buildResources() {
//        (vertexBuffer, indexBuffer) = SphereGenerator.sphereWithRadius(1, stacks: 30, slices: 30, device: device!)
        //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)

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


            //Sky
            let passDescriptor = MTLRenderPassDescriptor()
            passDescrForSky(passDescriptor, drawable: drawable)
            passDescrForModel(passDescriptor, drawable: drawable)

            //Sky
            let commandEncoderSky = commandBufferSky.renderCommandEncoderWithDescriptor(passDescriptor)

            commandEncoderSky.setRenderPipelineState(pipelineSky)
            commandEncoderSky.setDepthStencilState(depthStencilState)
            commandEncoderSky.setFrontFacingWinding(.CounterClockwise)
            commandEncoderSky.setCullMode(.Back)
            pointCloudDraw(commandEncoderSky)
            skyDraw(commandEncoderSky)
            commandEncoderSky.endEncoding()
            commandBufferSky.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()
        }
    }

    func passDescrForModel(passDescriptor: MTLRenderPassDescriptor, drawable: CAMetalDrawable) -> 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(passDescriptor: MTLRenderPassDescriptor, drawable: CAMetalDrawable) -> 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.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.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)
    }

enter image description here

这里是天空的顶点缓冲区:

struct Vector4
{
    var x: Float32
    var y: Float32
    var z: Float32
    var w: Float32
}

struct TexCoords
{
    var u: Float32
    var v: Float32
}

struct Vertex
{
    var position: Vector4
    var normal: Vector4
    var texCoords: TexCoords
}

var vertexCountSky: Int = 0

struct SkySphere
{
    static func sphere(device: MTLDevice) -> (MTLBuffer!)
    {

        let ply = plyVntReader.init(objFileName: "test")
        let vertexBuffer = device.newBufferWithBytes(ply!.vertices, length:sizeof(Vertex) * ply!.vertexCount, options:.OptionCPUCacheModeDefault)

        print(ply!.vertices)
        vertexCountSky = ply!.vertexCount
        return (vertexBuffer)

    }
}

这是模型的顶点缓冲区:

var vertextCountModel: Int = 0

struct PointCloud
{
    static func model(device: MTLDevice) -> (MTLBuffer!, MTLBuffer!, MTLBuffer!)
    {

        let ply = plyVncReader.init(objFileName: "controller_ascii")
        vertextCountModel = ply!.vertexCount

        let vertexBuffer = device.newBufferWithBytes(ply!.vertices, length:sizeof(V4f) * ply!.vertexCount, options:.OptionCPUCacheModeDefault)
        let normalBuffer = device.newBufferWithBytes(ply!.normals, length:sizeof(V4f) * ply!.vertexCount, options:.OptionCPUCacheModeDefault)
        let colorBuffer = device.newBufferWithBytes(ply!.colors, length:sizeof(V4f) * ply!.vertexCount, options:.OptionCPUCacheModeDefault)

        print(ply!.colors)
        return (vertexBuffer, normalBuffer, colorBuffer)

    }
}

天空着色器

using namespace metal;

//Sky
struct TexturedInVertex
{
    packed_float4 position [[attribute(0)]];
    packed_float4 normal [[attribute(1)]];
    packed_float2 texCoords [[attribute(2)]];

};

struct TexturedColoredOutVertex
{
    float4 position [[position]];
    float3 normal;
    float2 texCoords;
    float pointsize[[point_size]];

};

struct UniformsSky
{
    float4x4 projectionMatrix;
    float4x4 modelViewMatrix;
};

vertex TexturedColoredOutVertex vertex_sky(device TexturedInVertex *vert [[buffer(0)]],
                                           constant UniformsSky &uniforms [[buffer(1)]],
                                           uint vid [[vertex_id]])
{
    float4x4 MV = uniforms.modelViewMatrix;
    float3x3 normalMatrix(MV[0].xyz, MV[1].xyz, MV[2].xyz);
    float4 modelNormal = vert[vid].normal;

    TexturedColoredOutVertex outVertex;
    outVertex.position = uniforms.projectionMatrix * uniforms.modelViewMatrix * float4(vert[vid].position);
    outVertex.normal = normalMatrix * modelNormal.xyz;
    outVertex.texCoords = vert[vid].texCoords;
    outVertex.pointsize = 10.0;

    return outVertex;
};

fragment half4 fragment_sky(TexturedColoredOutVertex vert [[stage_in]],
                            texture2d<float, access::sample> diffuseTexture [[texture(0)]],
                            sampler samplr [[sampler(0)]])
{
    float4 diffuseColor = diffuseTexture.sample(samplr, vert.texCoords);
    return half4(diffuseColor.r, diffuseColor.g, diffuseColor.b, 1);
};

这是模型的着色器 //模型

struct ColoredVertex
{
    float4 position [[position]];
    float4 normal;
    float4 color;
    float pointsize[[point_size]];

};

struct UniformsPoint
{
    float4x4 projectionMatrix;
    float4x4 modelViewMatrix;
};

vertex ColoredVertex vertex_ply(constant float4 *position [[buffer(0)]],
                                constant float4 *normal [[buffer(1)]],
                                constant float4 *color [[buffer(2)]],
                                constant UniformsPoint &uniforms [[buffer(3)]],
                                uint vid [[vertex_id]])
{    
    ColoredVertex vert;
    vert.position = uniforms.projectionMatrix * uniforms.modelViewMatrix * position[vid];
    vert.normal = normal[vid];
    vert.color = color[vid];
    vert.pointsize = 5.0;

    return vert;
}

fragment float4 fragment_ply(ColoredVertex vert [[stage_in]])
{
    return vert.color;
}

0 个答案:

没有答案