【问题标题】:Metal off-screen drawing with Multi-Sampling使用多重采样的金属离屏绘图
【发布时间】:2016-04-21 15:07:43
【问题描述】:

如何将图元渲染到屏幕外纹理,而不是直接渲染到屏幕中?

我有一组三角形和相应的颜色,我只想用与屏幕相同的方式绘制它们,但绘制成屏幕外纹理,我可以将其保存到文件中。

谁能给我看一个代码示例?

【问题讨论】:

  • 你试过什么?在 Metal 中,所有的渲染都是针对纹理完成的;唯一的区别是您是绘制到一个包含在可绘制对象中然后呈现到屏幕上的纹理,还是您自己管理的纹理。如果要绘制后者,只需创建一个适当大小和格式的MTLTexture 并将其设置为渲染通道描述符的第一个颜色附件的纹理。然后,您可以使用getBytes API 获取图像数据并将其写入。
  • 看我的代码,我已经更新了问题
  • 我想我的问题是我的坐标是错误的,也许我应该设置视口或者自定义投影......
  • 对,您应该从顶点着色器返回剪辑空间坐标。如果您的顶点尚未在该空间中指定,您将需要使用某种投影矩阵将它们移动到其中。
  • 如果您的顶点位于基于像素的坐标中,则可以使用正交投影矩阵对它们进行缩放和偏置,以使 x 和 y 始终介于 -1 和 1 之间。请参阅this article 中的makeOrthographicMatrix

标签: ios objective-c swift metal


【解决方案1】:

好的,我自己意识到了。这段代码完成了这项工作,唯一的例外是它绘制了太大的三角形,但这是 Vertex 函数的不同主题。

这是我的代码:

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

您的图像现在位于outTexture 变量中。

【讨论】:

  • 我今天碰巧遇到了同样的问题,但仍然有奇怪的问题。我认为解决我自己问题的方法是使用 .MultisampleResolve,但是 outTexture 的描述符的设置是什么?
猜你喜欢
  • 2019-01-14
  • 1970-01-01
  • 2019-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多