私はこれを正しく理解していることを確認したいだけです(SO Chatでお願いしますが、そこは死んでいます!):
頂点配列があり、これをバインドすることで「現在」になります
次に、ターゲットにバインドするバッファーがあります
その後、glBufferData
を介してそのターゲットを満たします。これは、基本的にそのターゲットにバインドされたもの、つまりバッファ
次に、glVertexAttribPointer
を呼び出します。これは、データがどのようにレイアウトされているかを示します。データは、GL_ARRAY_BUFFER
そして、この記述子は元の頂点配列に保存されます
(1)私の理解は正しいですか?
documentation は、すべてがどのように相関するかについて少し疎です。
(2)ある種のデフォルトの頂点配列はありますか? glGenVertexArrays
とglBindVertexArray
を忘れてしまったので、私のプログラムはそれなしでもうまく機能したからです。
編集:ステップを逃しました... glEnableVertexAttribArray
。
(3)glVertexAttribPointer
が呼び出された時点で頂点配列に頂点配列が関連付けられており、どの頂点配列に関係なく、glEnableVertexAttribArray
を介してその属性をいつでも有効/無効にできます。現在バインドされていますか?
または(3b)glEnableVertexAttribArray
が呼び出されたときに頂点配列が頂点配列に関連付けられているため、glEnableVertexAttribArray
を異なる時間に呼び出して、同じ頂点属性を複数の頂点配列に追加できます。異なる頂点配列がバインドされているとき?
一部の用語は少しずれています。
Vertex Array
は、頂点データを含む単なる配列(通常はfloat[]
)です。何にもバインドする必要はありません。後で説明するVertex Array Object
またはVAOと混同しないでくださいBuffer Object
は、頂点(略してVBO)を格納するときに一般的にVertex Buffer Object
と呼ばれ、単にBuffer
と呼んでいます。glVertexAttribPointer
は、glVertexPointer
またはglTexCoordPointer
とまったく同じように機能します。名前付き属性の代わりに、独自の属性を指定する番号を指定できます。この値をindex
として渡します。 glVertexAttribPointer
呼び出しはすべて、次回glDrawArrays
またはglDrawElements
を呼び出すときにキューに入れられます。 VAOがバインドされている場合、VAOはすべての属性の設定を保存します。ここでの主な問題は、頂点属性とVAOを混同していることです。頂点属性は、描画のために頂点、テックス座標、法線などを定義する新しい方法です。 VAOは状態を保存します。最初に、描画が頂点属性でどのように機能するかを説明し、次にVAOでメソッド呼び出しの数を削減する方法を説明します。
glEnableVertexAttribArray(0);
で頂点を有効にする必要があります。glBindBuffer(GL_ARRAY_BUFFER, myBuffer);
をバインドする必要があります。glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
を定義できます。パラメーターの順序:0は定義する属性、3は各頂点のサイズ、GL_FLOAT
はタイプ、GL_FALSE
は各頂点を正規化しないことを意味し、最後の2つのゼロは頂点にストライドまたはオフセットはありません。glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(0);
これをglUseProgram()
呼び出しでラップすると、シェーダーで適切に動作するレンダリングシステムが得られます。しかし、5つの異なる属性、頂点、Texcoord、法線、色、およびライトマップ座標があるとします。まず、これらの属性のそれぞれに対して単一のglVertexAttribPointer
呼び出しを行うことになり、事前にすべての属性を有効にする必要があります。リストに属性0〜4を定義するとします。次のようにすべてを有効にします。
for (int i = 0; i < 5; i++)
glEnableVertexAttribArray(i);
そして、属性ごとに異なるVBOをバインドする必要があります(すべてを1つのVBOに格納し、オフセット/ストライドを使用しない限り)。次に、頂点のglVertexAttribPointer(0,...);
からライトマップ座標までのglVertexAttribPointer(4,...);
の5つの異なるglVertexAttribPointer
呼び出しを行う必要があります。
うまくいけば、そのシステムだけで意味があります。次に、VAOに進み、このタイプのレンダリングを行う際にVAOを使用してメソッド呼び出しの回数を削減する方法を説明します。 VAOを使用する必要はないことに注意してください。
Vertex Array Object
またはVAOは、すべてのglVertexAttribPointer
呼び出しの状態と、glVertexAttribPointer
呼び出しのそれぞれが行われたときにターゲットにされたVBOを格納するために使用されます。
glGenVertexArrays
を呼び出して生成します。必要なものをすべてVAOに保存するには、glBindVertexArray
でバインドします、次に完全な描画呼び出しを行います。全ての ドロー バインド呼び出しは、VAOによってインターセプトされ、保存されます。 glBindVertexArray(0);
でVAOのバインドを解除できます
オブジェクトを描画するときに、すべてのVBOバインドまたはglVertexAttribPointer
呼び出しを再呼び出しする必要はありません。VAOをglBindVertexArray
でバインドし、glDrawArrays
またはglDrawElements
を呼び出すだけで、まったく同じものを描画できます。これらすべてのメソッド呼び出しを行っているかのように。おそらく、後でVAOのバインドを解除することもできます。
VAOのバインドを解除すると、VAOをバインドする前の状態にすべての状態が戻ります。 VAOのバインド中に行った変更が保持されるかどうかはわかりませんが、テストプログラムを使用すると簡単にわかります。 glBindVertexArray(0);
は「デフォルト」VAOへのバインドと考えることができると思います...
更新:誰かが実際の描画呼び出しの必要性に気付いた。結局のところ、VAOをセットアップするときに実際にFULL描画呼び出しを実行する必要はなく、すべてのバインディングのことだけが必要です。以前に必要だと思った理由がわかりませんが、現在は修正されています。
呼び出されるAPIの用語とシーケンスは、非常に紛らわしいです。さらに紛らわしいのは、バッファ、汎用頂点属性、シェーダー属性変数のさまざまな側面がどのように関連付けられるかです。 OpenGL-Terminology を参照してください。
さらに、リンク OpenGL-VBO、shader、VAO は、必要なAPI呼び出しの簡単な例を示しています。特に、即時モードからプログラム可能なパイプラインに移行する場合に適しています。
それが役に立てば幸い。
編集:以下のコメントからわかるように、人々は仮定を立てて結論にジャンプすることができます。現実には、初心者にとっては非常に混乱します。