8

を介してバッファをバインドする場合glBindBuffer()、ターゲットがへの別の呼び出しによって再バインドされるまで、バッファはバインドされたままであると安全に想定できると確信していましたglBindBuffer()glBindVertexArray()したがって、呼び出しによってGL_ELEMENT_ARRAYターゲットにバインドされたバッファーが0に設定されることを発見したとき、私は非常に驚きました。

最小限のC++サンプルコードは次のとおりです。

GLuint buff;
glGenBuffers(1, &buff);
std::cout << "Buffer is " << buff << "\n";
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buff);
GLuint vao;
glGenVertexArrays(1, &vao);

GLint bound_buff;
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &bound_buff);
std::cout << "Bound before glBindVertexArray: " << bound_buff << "\n";

glBindVertexArray(vao);    
  // ^- an implicit glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); ?

glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &bound_buff);
std::cout << "Bound after glBindVertexArray: " << bound_buff << "\n";

OpenGL 3.2デバイスコンテキストを初期化した直後にこのコードを実行すると、次の出力が得られます。

 Buffer is 1
 Bound before glBindVertexArray: 1
 Bound after glBindVertexArray: 0

一方、GL_ARRAY_BUFFERは呼び出しによって変更されません。OpenGL 3.2仕様(2.10)を確認しましたglBindVertexArrayが、予期しない副作用については言及されていませんでした。

  1. この動作は仕様に準拠していますか?
  2. もしそうなら、への呼び出しから他にどのような副作用が予想されglBindVertexArrayますか?
  3. この背後にある理論的根拠は何ですか?

296.10WHQLドライバーを搭載したWinXPx64マシンのnvidiaカードでこれをテストしました。nvidiaGT330Mを使用したOSXLionでの簡単なテストでも、同じ結果が得られました。

4

1 に答える 1

15

頂点配列オブジェクトは、頂点データのレンダリングに必要なすべての状態*をカプセル化します。glVertexAttribPointerしたがって、属性(を介して)、GL_ELEMENT_ARRAY_BUFFER(呼び出しに必要)などに関連付けたバッファーをカプセル化する必要がありglDrawElement*ます。

しかし、ドキュメントにこの副作用についての言及が見つからなかったという事実に、私はまだ少し戸惑いを感じています。

仕様はこれを明確に説明していますが、仕様がどのように機能するかを理解する必要があります。

OpenGLは状態のコレクションです。つまり、すべてのOpenGL関数(実際に何かをレンダリングする関数を除く)がOpenGLの状態を変更します。を呼び出すとglVertexAttribPointer、この関数は概念的に内部OpenGL状態の一部を変更します。

OpenGLオブジェクトは、カプセル化するOpenGL状態のどの部分によって定義されます。したがって、関数がオブジェクトによってカプセル化された状態を変更する場合、その関数はオブジェクト自体を変更します。オブジェクトのバインドとは、カプセル化する現在の状態をそのオブジェクトの現在の状態に置き換えることを意味します。

ARB_vertex_array_object仕様は、カプセル化する状態に基づいてVAOを定義します。基本的に、OpenGL状態テーブルの1つを指し、「VAOはそのすべてです」と述べています。この機能のコア3.xバージョンは、実際には状態テーブルを変更して、もう少し明確にします(同じ動作、わずかに異なる説明)。

OpenGL 3.3仕様、セクション2.10:

結果の頂点配列オブジェクトは、表6.4および6.5にリストされているすべての状態値を含む新しい状態ベクトルです。

表6.4と6.5を転載するつもりはありません。あなたはそれらを自分で調べることができます。しかし、それらには明らかにGL_ELEMENT_ARRAY_BUFFER_BINDINGさまざまなGL_VERTEX_ATTRIB_ARRAY_BUFFER_BIDNINGもの(バッファオブジェクト)が含まれています。

*注:VAOには、関数によって設定された状態は含まれていませんglVertexAttrib。属性配列が有効になっていない場合、これらはレンダリングに影響を与える可能性があります。

于 2012-04-07T16:09:39.613 に答える