【问题标题】:What is the proper way to dynamically change the color of a vertex in Metal?在 Metal 中动态更改顶点颜色的正确方法是什么?
【发布时间】:2015-06-15 17:30:15
【问题描述】:

我正在尝试进入 Metal。我已经做了一些 OpenGL,但已经有好几年了,所以我想不出合适的方法来做到这一点。我一直在使用 Ray Wenderlich (http://www.raywenderlich.com/81399/ios-8-metal-tutorial-swift-moving-to-3d) 上的 Metal 入门教程

我有一个顶点结构:

struct Vertex
{
    var x, y, z: Float
    var r, g, b, a: Float

    func floatBuffer() -> Array<Float>
    {
        return [x, y, z, r, g, b, a]
    }
}

还有一个顶点缓冲类:

class VertexBuffer
{
    var vertexData = Array<Float>()

    init(vertices: Array<Vertex>)
    {
        var vertexData = Array<Float>()

        for vertex in vertices
        {
            vertexData += vertex.floatBuffer()
        }

        self.vertexData = vertexData
    }

    func updateColorOfVertexAtIndex(index: Int, newRed: CGFloat, newGreen: CGFloat, newBlue: CGFloat, newAlpha: CGFloat)
    {
        let vertexDataIndex = index * 7

        if (vertexDataIndex < self.vertexData.count)
        {
            self.vertexData[vertexDataIndex + 3] = Float(newRed)
            self.vertexData[vertexDataIndex + 4] = Float(newGreen)
            self.vertexData[vertexDataIndex + 5] = Float(newBlue)
            self.vertexData[vertexDataIndex + 6] = Float(newAlpha)
        }
    }

    func updateColorOfVertexAtIndex(index: Int, newColor: UIColor)
    {
        var red: CGFloat = 0.0
        var green: CGFloat = 0.0
        var blue: CGFloat = 0.0
        var alpha: CGFloat = 0.0

        newColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)

        self.updateColorOfVertexAtIndex(index, newRed: red, newGreen: green, newBlue: blue, newAlpha: alpha)
    }
}

基于其他一些应用程序的状态,我想更新一个或多个顶点的 RGBA。使用VertexBuffer.updateColor... 方法,我正在更新VertexBuffer.vertexData 中相应的RGBA 值。我有一个 CADisplayLink 连接到以下功能:

func diffusionLoop()
{
    self.updateVertexData()

    var vertexData = self.inkVertexBuffer.vertexData

    let dataSize = vertexData.count * sizeofValue(vertexData[0])
    let vertexBuffer = self.device.newBufferWithBytes(vertexData, length: dataSize, options: nil)


    autoreleasepool { () -> () in
        self.renderColorsWithVertexBuffer(vertexBuffer)
    }
}

func renderColorsWithVertexBuffer(vertexBuffer: MTLBuffer)
    {
        let renderPassDescriptor = MTLRenderPassDescriptor()
        let drawable = self.metalLayer.nextDrawable()

        renderPassDescriptor.colorAttachments[0].texture = drawable.texture
        renderPassDescriptor.colorAttachments[0].loadAction = .Clear
        renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(1.0, 1.0, 1.0, 0.0)
        renderPassDescriptor.colorAttachments[0].storeAction = .Store

        let commandBuffer = self.commandQueue.commandBuffer()

        if let renderEncoder = commandBuffer.renderCommandEncoderWithDescriptor(renderPassDescriptor) {
            renderEncoder.setRenderPipelineState(self.pipelineState)
            renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, atIndex: 0)
            renderEncoder.drawPrimitives(.Triangle, vertexStart: 0, vertexCount: self.vertexCount, instanceCount: self.triangleCount)
            renderEncoder.endEncoding()
        }

        commandBuffer.presentDrawable(drawable)
        commandBuffer.commit()
    }

问题是,我不知道这是否是正确的方法。我的目标是经常更新某些顶点的颜色,但是每次修改顶点数据并从中创建一个 MTLBuffer 的答案是什么?还是别的什么?

任何帮助将不胜感激!

【问题讨论】:

    标签: ios swift metal


    【解决方案1】:

    理想情况下,您不希望更新 vertexBuffer 的值。在我看来,最好的方法,你想要做的,是将不可变数据与可变数据分开。

    所以我会用颜色值创建单独的统一缓冲区并更新它而不是 vertexBuffer 本身。

    您还说“基于其他一些应用程序的状态,我想更新一个或多个顶点的 RGBA ...”,这可能会更好将这些“states”作为常量传递给着色器和着色器内部,以计算每个顶点或片段的颜色。

    顶点着色器有:

    unsigned int vid [[ vertex_id ]]
    

    您可以使用它为每个顶点显式设置颜色。

    【讨论】:

    • 嘿,这个答案对我也有帮助。你能为我提供一些澄清吗?我在文档中读到 MTLBuffers 是为了被重用,你应该尽可能避免创建新的。但是,如果您想更新每一帧的颜色,在我看来,您必须这样做。那么,通过将颜色与顶点分开,您只是重新创建尽可能多的存储空间吗?
    • @lancejabr 你是绝对正确的,在每个绘图调用上分配缓冲区是一种不好的做法。您需要做的是分配缓冲区池并重用它们,就像使用 UITableView 单元格一样。在我的教程raywenderlich.com/93997/… 部分“重用统一缓冲区(可选)”中有对此的解释。我认为您不应该在顶点数据中包含可变颜色数据,而应该通过统一缓冲区传递它,并在着色器中从中读取颜色。
    猜你喜欢
    • 2020-05-28
    • 2021-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多