6

新しい (OpenGL 4.3 以降) glBindVertexBuffer メカニズムを使用して、2 つの VAO を設定するとします。

glGenVertexArrays(1, &vaoIndex0);
glGenVertexArrays(1, &vaoIndex1);

...

glBindVertexArray(vaoIndex0)
glBindVertexBuffer(bindingIndex0, ...)
glEnableVertexAttribArray(0)
glVertexAttribFormat(0, ...)
glVertexAttribBinding(0, bindingIndex0)
...
glBindVertexArray(0)

...

glBindVertexArray(vaoIndex1)
glBindVertexBuffer(bindingIndex1, ...)
glEnableVertexAttribArray(0)
glVertexAttribFormat(0, ...)
glVertexAttribBinding(0, bindingIndex1)
...
glBindVertexArray(0)

そして、同じ OpenGL コンテキストに存在する場合を除いて、2 つが独立しているとします。それらは異なるバッファーをバインドし、異なるものを描画するために使用されます。

bindingIndex0 は bindingIndex1 と異なる必要がありますか? 2 つの指標が等しい (または等しくない) ことには、まったく意味がありますか?

...

編集:

回答を受け取った後、「頂点バッファー バインディング ポイント」とは何か、特にその範囲を実際に知っている人にとって、私の質問は私が意図したものとは異なることを尋ねているように見えるかもしれないことを理解し始めました。おそらく、より適切な言い回しは、「競合を防ぐために、複数の VAO 間であっても、OpenGL 頂点バッファー バインディング ポイントインデックスが再利用されるのを防ぐために、自分のやり方を変える必要がありますか?」でした。しかし、とにかく、両方の質問に答えたようです: いいえ、「バインディング ポイント」を再利用することはできません。また、インデックスの競合をそのように回避する必要はありません。

4

1 に答える 1

7

これらの呼び出しはすべて、VAO の状態を変更します。いいえ、VAO 間でこれらの設定を再利用することはできません。もちろん、複数の VAO で同じように設定することもできますが、各 VAO を設定するときに、必要な状態設定呼び出しを 1 回行う必要があります。

bindingIndex0コード フラグメントで使用するとのbindingIndex1値には、特別な意味はありません。これらは、 でバインディング インデックスにバインドするバッファと、glBindVertexBuffer()そのバインディング インデックスを使用するように指定した属性との間の接続を確立するだけです。

唯一の条件は、バインディング インデックスが、クエリできる値よりも小さい必要があることですMAX_VERTEX_ATTRIB_BINDINGS。これは、少なくとも 16 であることが保証されています。これらの呼び出しは、VAO ごとの状態を変更するため、複数の VAO に対して同じバインディング インデックスを絶対に使用できます。

これらの新しい状態設定呼び出しを調べる 1 つの方法は、以前は利用できなかったレベルの間接化を導入することです。

  • glVertexAttribPointer()これらの呼び出しがなければ、目的のバッファーがバインドされている間に呼び出すことで、頂点属性とバッファーの間の直接接続を確立します。
  • これらの新しい呼び出しにより、頂点アトリビュートは で確立されたバインディング インデックスに接続されるようになりましたglVertexAttribBinding()。バインディング インデックスは、 で確立されたバッファに接続されglBindVertexBuffer()ます。

つまり、古いスタイルでは、接続は次のようになります。

attribute index --> buffer

これらの 4.3+ 呼び出しによる新しいスタイル:

attribute index --> buffer index --> buffer

この新しい柔軟性の利点の 1 つは、1 回の呼び出しで新しいバッファーを複数の属性にバインドできることです。これらすべての属性が同じバッファー インデックスを持っている限り、すべての属性に対してglBindVertexBuffer()新しいバッファーを指定するために を 1 回呼び出すだけで済みます。

セミフォーマルな定義

以下は公式表記ではありません。私はちょうどそれを作りました。しかし、いくつかの疑似データ構造を書き留めて、関係をより正式に定義すると役立つかもしれないと思いました。

上記で説明した接続をキャプチャするために、各 VAO に 2 つの配列が含まれているとします。

struct VAO {
    ...
    uint bufferIndexBindings[MAX_VERTEX_ATTRIB_BINDINGS];
    uint attribBufferIndices[MAX_VERTEX_ATTRIBS];
}

ここで説明した 2 つの呼び出しは、この構造を次のように変更します。

glBindVertexBuffer(uint bindingIndex, uint buffer, ...) {
    CurrentVAO.bufferIndexBindings[bindingIndex] = buffer;
}

glVertexAttribBinding(uint attribIndex, uint bindingIndex) {
    CurrentVAO.attribBufferIndices[attribIndex] = bindingIndex;
}

次に、この状態を使用して、次のようなインデックスを持つ特定の属性のバッファーを取得しますattribIndex

CurrentVAO.bufferIndexBindings[CurrentVAO.attribBufferIndices[attribIndex]]

これは、上で説明した間接化も示しています。これは、状態テーブルへの 2 レベルのルックアップとしてここに示されています。

于 2015-03-24T02:59:07.410 に答える