28

私は OpenGL を使用して小さなグラフィック エンジンを作成しています (C# を使用した OpenTK 経由)。

頂点属性を定義するために、glEnableVertexAttribArray/glVertexAttribPointer 呼び出しにマップされる VertexElement 構造体の配列を持つ VertexDeclaration クラスがあります。

また、複数の頂点ストリームをサポートするために、頂点バッファー、頂点宣言、頂点オフセット、およびインスタンス頻度 (XNA の VertexBufferBinding 構造のような) を保持する特別な構造があります。

現在、描画呼び出しが呼び出されるたびに、設定されたすべての頂点ストリームを繰り返し処理し、それらの頂点バッファーをバインドし、頂点宣言を適用し、未使用の頂点属性を無効にして、プリミティブを描画します。

VAO を使用して glEnableVertexAttribArray 呼び出しをそれらにキャッシュし、頂点ストリームが適用されるたびに、VAO をバインドし、配列バッファーのバインドを変更したいと考えています。

それはVAOの正しい使い方ですか?

4

1 に答える 1

56

それはVAOの正しい使い方ですか?

いいえ1

glVertexAttribPointer GL_ARRAY_BUFFER 関数が呼び出された時点でバインドされていたバッファ オブジェクトを使用します。したがって、これを行うことはできません:

glVertexAttribPointer(...);
glBindBuffer(GL_ARRAY_BUFFER, bufferObject);
glDrawArrays(...);

これは使用しませんbufferObject。が最初に呼び出されたGL_ARRAY_BUFFERときにバインドされていたものを使用します。glVertexAttribPointer

VAO はこの状態をキャプチャします。そのため、VAO は、頂点属性ごとに、GL_ARRAY_BUFFER呼び出されたときにバインドされたバッファー オブジェクトを格納します。これにより、次のようなことができます。

glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, buffer1);
glVertexAttribPointer(0, ...);
glVertexAttribPointer(1, ...);
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
glVertexAttribPointer(2, ...);

アトリビュート 0 と 1 は から取得されbuffer1、アトリビュート 2 は から取得されbuffer2ます。VAO は、その状態をすべてキャプチャするようになりました。レンダリングするには、次のようにします。

glBindVertexArray(VAO);
glDraw*();

つまり、属性のストレージが OpenGL でどこから来るかを変更したい場合は、そのformatも変更する必要があります。同じフォーマットであっても、再度呼び出す必要がありますglVertexAttribPointer

1 : この説明は、新しいARB_vertex_attrib_bindingを使用していないことを前提としています。または、別の方法で知られているように、「Direct3D が頂点属性バインディングを行う方法とまったく同じです。」 この拡張機能を提供する実装を使用している場合は、属性形式が関連付けられていないため、話していることを効果的に行うことができます。バッファ オブジェクトのストレージ。また、の拷問された論理はなくなりました。glVertexAttribPointer

一般に、OpenGL の世界でこれを解決する方法は、できるだけ多くのものを同じバッファー オブジェクトに入れることです。それができない場合は、オブジェクトごとに 1 つの VAO を使用してください。

于 2013-01-10T02:25:48.267 に答える