いくつかの用語は少しずれています:
- A
Vertex Array
は、float[]
頂点データを含む単なる配列(通常は)です。何かにバインドする必要はありません。Vertex Array Object
またはVAO と混同しないでください。後で説明します。
- Aは
Buffer Object
、一般に呼ばれるVertex Buffer Object
VBOが短いため頂点を格納するとき、または、あなただけ呼んでいるものですBuffer
。
- 何も頂点配列に背を保存されません取得し、
glVertexAttribPointer
正確に同じように動作しglVertexPointer
たりglTexCoordPointer
だけではなく、指定された属性の仕事、あなたがあなた自身の属性を指定する番号を提供してもらいます。この値はとして渡しますindex
。すべてのglVertexAttribPointer
通話は、次回glDrawArrays
またはを呼び出すときにキューに入れられますglDrawElements
。VAOバインドがある場合、VAOはすべての属性の設定を保存します。
ここでの主な問題は、頂点属性をVAOと混同していることです。頂点属性は、描画のために頂点、texcoord、法線などを定義する新しい方法です。VAOは状態を格納します。最初に、描画が頂点属性でどのように機能するかを説明し、次に、VAOを使用してメソッド呼び出しの数を削減する方法を説明します。
- シェーダーで使用する前に、属性を有効にする必要があります。たとえば、頂点をシェーダーに送信する場合は、最初の属性0として送信する可能性があります。そのため、レンダリングする前に、で有効にする必要があります
glEnableVertexAttribArray(0);
。
- 属性が有効になったので、使用するデータを定義する必要があります。そのためには、VBO-をバインドする必要があります
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);
- 次に描画するものは属性0を使用しない場合があります(実際には使用しますが、これは例です)。これを無効にできます-
glDisableVertexAttribArray(0);
これをglUseProgram()
呼び出しでラップすると、シェーダーを適切に処理するレンダリングシステムができます。しかし、5つの異なる属性、頂点、texcoords、法線、カラー、ライトマップ座標があるとします。まず最初にglVertexAttribPointer
、これらの各属性に対して1 回の呼び出しを行うことになるため、事前にすべての属性を有効にする必要があります。リストにある属性0〜4を定義するとします。あなたはそのようにそれらのすべてを有効にします:
for (int i = 0; i < 5; i++)
glEnableVertexAttribArray(i);
そして、あなたは(あなたがすべて1 VBOと利用オフセット/ストライドに保存していない限り)属性ごとに異なるVBOsをバインドしなければならない、あなたは5つの異なるようにする必要がありglVertexAttribPointer
からの呼び出し、glVertexAttribPointer(0,...);
にglVertexAttribPointer(4,...);
それぞれライトマップ座標に頂点のために。
うまくいけば、そのシステムだけでも理にかなっています。次に、VAOを使用して、このタイプのレンダリングを実行するときに、VAOを使用してメソッド呼び出しの数を削減する方法を説明します。VAOを使用する必要がないことに注意してください。
A Vertex Array Object
又はVAOは、すべての状態を格納するために使用されるglVertexAttribPointer
コールとの各場合に標的としたVBOs glVertexAttribPointer
呼び出しが行われたが。
を呼び出して生成しglGenVertexArrays
ます。必要なものをすべてVAOに保存するにはglBindVertexArray
、それをにバインドしてから、完全な描画呼び出しを実行します。すべての描画バインド呼び出しは、VAOによってインターセプトされ、保存されます。VAOをバインド解除するにはglBindVertexArray(0);
あなたがオブジェクトを描画したい場合、あなたは再呼び出し、すべてのVBOが結合またはする必要はありません今glVertexAttribPointer
の呼び出し、あなただけでVAOをバインドする必要がglBindVertexArray
コールしglDrawArrays
たりglDrawElements
、あなたがあなたかのようにまったく同じことを描画することがありますそれらすべてのメソッド呼び出しを行っていました。後でVAOのバインドを解除することもできます。
VAOをバインド解除すると、すべての状態は、VAOをバインドする前の状態に戻ります。VAOがバインドされている間に行った変更が保持されるかどうかはわかりませんが、テストプログラムで簡単に把握できます。glBindVertexArray(0);
「デフォルト」のVAOへのバインドと考えることができると思います...
更新:誰かが私の実際のドローコールの必要性に注意を向けました。結局のところ、VAOを設定するときに実際にFULL Draw呼び出しを実行する必要はなく、すべてのバインディング要素を実行するだけです。なぜそれが以前に必要だったと思ったのかわかりませんが、現在は修正されています。