Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Metal off-screen drawing with Multi-Sampling

How do I render primitives into off screen texture, not directly into the screen?

I have a set of triangles and corresponding color, I just want to draw them the same way I do to screen, but into off screen texture, that I can save into a file.

Can anybody show me a code sample of that?

like image 251
s1ddok Avatar asked Apr 21 '16 15:04

s1ddok


1 Answers

Ok, I realized it myself. This code does the job, with only exception that it draw too huge triangles, but that is a different topic for Vertex function.

Here is my code:

    let fragmentProgram = defaultLibrary.newFunctionWithName("image_fragmentT")
    let vertexProgram = defaultLibrary.newFunctionWithName("image_vertexT")


    struct VertexT {
        var x, y, z, w : Float
        var r, g, b, a : Float
    }

    let vertexDescriptor = MTLVertexDescriptor()
    vertexDescriptor.attributes[0].offset = 0
    vertexDescriptor.attributes[0].format = .Float4
    vertexDescriptor.attributes[0].bufferIndex = 0

    vertexDescriptor.attributes[1].offset = 0
    vertexDescriptor.attributes[1].format = .Float4
    vertexDescriptor.attributes[1].bufferIndex = 0

    vertexDescriptor.layouts[0].stepFunction = .PerVertex
    vertexDescriptor.layouts[0].stride = sizeof(VertexT)

    let pipelineStateDescriptor = MTLRenderPipelineDescriptor()
    pipelineStateDescriptor.vertexDescriptor = vertexDescriptor
    pipelineStateDescriptor.vertexFunction = vertexProgram
    pipelineStateDescriptor.fragmentFunction = fragmentProgram
    pipelineStateDescriptor.colorAttachments[0].pixelFormat = .RGBA8Unorm;
    pipelineStateDescriptor.colorAttachments[0].blendingEnabled = true
    pipelineStateDescriptor.sampleCount = 4
    pipelineStateDescriptor.colorAttachments[0].rgbBlendOperation =    MTLBlendOperation.Add
    pipelineStateDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperation.Add
    pipelineStateDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactor.SourceAlpha
    pipelineStateDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactor.SourceAlpha
    pipelineStateDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactor.OneMinusSourceAlpha
    pipelineStateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactor.OneMinusSourceAlpha


    let sampleDesc = MTLTextureDescriptor()
    sampleDesc.textureType = MTLTextureType.Type2DMultisample
    sampleDesc.width = inTexture.width
    sampleDesc.height = inTexture.height
    sampleDesc.sampleCount = 4
    sampleDesc.pixelFormat = .RGBA8Unorm
    sampleDesc.storageMode = .Private
    sampleDesc.usage = .RenderTarget

    let sampletex = device.device.newTextureWithDescriptor(sampleDesc)
    let renderPassDescriptor = MTLRenderPassDescriptor()

    renderPassDescriptor.colorAttachments[0].texture = sampletex
    renderPassDescriptor.colorAttachments[0].resolveTexture = outTexture
    renderPassDescriptor.colorAttachments[0].loadAction = .Clear
    renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0)
    renderPassDescriptor.colorAttachments[0].storeAction = .MultisampleResolve

    let renderCB = commandQueue.commandBuffer()

    let renderCommandEncoder = renderCB.renderCommandEncoderWithDescriptor(renderPassDescriptor)
    let pipelineState = try! device.device.newRenderPipelineStateWithDescriptor(pipelineStateDescriptor)
    renderCommandEncoder.setRenderPipelineState(pipelineState)

    let vertexBuf = device.device.newBufferWithLength(triangles.count * 3 * sizeof(VertexT), options: .CPUCacheModeDefaultCache)

    var vBufPointer = [VertexT]()

    for i in 0..<triangles.count {

        // create buffer here
    }

    memcpy(vertexBuf.contents(), &vBufPointer, triangles.count * 3 * sizeof(VertexT))

    renderCommandEncoder.setVertexBuffer(vertexBuf, offset: 0, atIndex: 0)
    renderCommandEncoder.drawPrimitives(.Triangle, vertexStart: 0, vertexCount: triangles.count * 3)
    renderCommandEncoder.endEncoding()
    renderCB.commit()
    renderCB.waitUntilCompleted()

You image now is in outTexture variable.

like image 126
s1ddok Avatar answered Oct 20 '22 04:10

s1ddok