1

私はメタルに入ろうとしています。私は OpenGL を少しやったことがありますが、何年も経っているので、これを行うための適切な方法が思いつきません。Ray Wenderlich ( http://www.raywenderlich.com/81399/ios-8-metal-tutorial-swift-moving-to-3d )のメタル チュートリアルのイントロを使用してきました。

私は頂点構造体を持っています:

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

他のアプリケーションの状態に基づいて、1 つまたは複数の頂点の RGBA を更新したいと考えています。メソッドを使用してVertexBuffer.updateColor...、対応する RGBA 値を で更新していますVertexBuffer.vertexData。以下の関数に接続された 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 を作成するのが答えですか? または、他の何か?

どんな助けでも大歓迎です!

4

1 に答える 1

2

理想的には、 vertexBufferの値を更新したくないでしょう。私の意見では、あなたがやろうとしていることは、不変データを可変データから分離することです。

したがって、色の値を持つ別のユニフォーム バッファを作成し、vertexBuffer自体の代わりに更新します。

また、「他のアプリケーションの状態に基づいて、1 つまたは複数の頂点の RGBA を更新したい ... 」と言いましたが、これらの「状態」を定数としてシェーダーとシェーダーの内部に渡して計算する方がよい場合があります。各頂点またはフラグメントの色。

頂点シェーダーには次のものがあります。

unsigned int vid [[ vertex_id ]]

各頂点の色を明示的に設定できます。

于 2015-04-10T07:20:16.467 に答える