6

この 2010 年の質問を見ると、最新の OpenGL の頂点バッファーに関して、ダイレクト ステート アクセスが利用できない場合はまだありますか? フレームバッファ、テクスチャなどで DSA を使用するようにグラフィックス ライブラリのほとんどを変更しましたが、頂点配列の状態を設定するために「バインド」する必要があります (配列のバインド、インデックス バッファのバインド、頂点バッファのバインド、配列のバインド解除など)。 )。

更新 1: BDL の回答から、パラメーターが何をするのか理解できませんでした。非常に単純な頂点バッファー (1 つの属性、位置) の単体テストでは、空白の画面が表示されます (頂点ストリームを記述する古い方法で問題なく動作しました)。単一の三角形を描画するだけで、インデックス バッファーは必要ありません。

これが私がやっていることです、コメントは私の理解です:

        ::glEnableVertexArrayAttrib(vao,        // VAO name.
                                    0);         // Attribute index (layout in shader).
        ::glVertexArrayVertexBuffer(vao,        // VAO name.
                                    0,          // Binding point.
                                    vbo,        // VBO name.
                                    12,         // Stride (bytes).
                                    0);         // Offset (bytes).
        ::glVertexArrayAttribFormat(vao,        // VAO name.
                                    0,          // Attribute index (layout in shader).
                                    3,          // Component count (x,y,z).
                                    GL_FLOAT,   // Type.
                                    GL_FALSE,   // Normalised.
                                    0);         // Offset (bytes).
        ::glVertexArrayAttribBinding(vao,       // VAO name.
                                     0,         // Attribute index (layout in shader).
                                     0);        // Binding point.

これで、バインディング ポイントについて「理解」したと思います。それらは、別の属性セットにすばやく簡単に交換できるように、割り当てることができる任意の番号です。したがって、この単純なテストには 0 を使用するだけで十分です。

glCreateBuffers を使用して vbo を作成し、glCreateVertexArrays を使用して vao を作成しています (以前のバインド可能なスタイルから変更されています)。デバッグ出力はなく (デバッグ コンテキストはオン)、すべての呼び出しは glGetError でチェックされ、エラーは報告されません。

更新 2: glVertexArrayVertexBuffer ストライドとオフセットの順序が間違っていました。それは今動作します。

更新 3: glVertexArrayVertexBuffer は、VBO 内の各属性に対して 1 回ではなく、1 回呼び出されます (位置、テクスチャなどをインターリーブしている場合)。

4

1 に答える 1

13

OpenGL 4.3 以降、ほとんどの VAO 状態は、状態への直接アクセスを使用して設定できます。次の関数を見てください。

void glVertexArrayAttribBinding  (GLuint vaobj, GLuint attribindex, GLuint bindingindex);

void glVertexArrayVertexBuffer   (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
void glVertexArrayBindingDivisor (GLuint vaobj, GLuint bindingindex, GLuint divisor);

void glEnableVertexArrayAttrib   (GLuint vaobj, GLuint attribindex);
void glDisableVertexArrayAttrib  (GLuint vaobj, GLuint attribindex);
void glVertexArrayAttribFormat   (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
void glVertexArrayAttribIFormat  (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
void glVertexArrayAttribLFormat  (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);

このスレッドで、それらの使用方法の例をいくつか見つけることができます。

原則として、「古い」VAO コードは 1 対 1 で DSA コードに変換できます。このような例があるとします

glBindVertexArray(vao);
glEnableVertexAttribArray(att_idx); //att_idx comes from shader
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(att_idx, 4, GL_FLOAT, GL_FALSE, sizeof(vec4), 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

次に、これは DSA コードで次のようになります。

//glBindVertexArray(vao);
//No translation needed, since we don't want to bind :)

//glEnableVertexAttribArray(att_idx);
glEnableVertexArrayAttrib(vao, att_idx);

それは簡単な部分でした。

//glBindBuffer(GL_ARRAY_BUFFER, vbo);
//glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glVertexArrayVertexBuffer(vao, 0, vbo, 0, sizeof(vec4));

バインディング ポイント <-> バッファーの対応を指定します。ここで、2 番目のパラメーターはバインディング ポイントです。GL_MAX_VERTEX_ATTRIB_BINDINGS 未満である限り、ここで基本的に必要なものを選択できます。しかし、私は通常、属性が持っているのと同じインデックスを使用することをお勧めします。パラメータ 3 と 4 (ストライド、オフセット) は、 と同じ値ですglVertexAttribPointerとは対照的に、0 のストライドが密集したデータを示すことを許可しないことに注意してください。データが密集している場合でも、ストライドはバイト単位で指定する必要があります。glVertexArrayVertexBufferglVertexAttribPointer

glVertexArrayAttribFormat(vao, att_idx, 4, GL_FLOAT, GL_FALSE, 0);

これは、属性の形式を定義します。値 3 ~ 5 は、 での対応に似ていglVertexAttribPointerます。最後のパラメーターは、バッファー内の要素間の相対オフセットです。

glVertexArrayAttribBinding(vao, att_idx, 0);

この行は、アトリビュート インデックスと で使用されるバインディング ポイントの間の対応を作成しますglVertexArrayVertexBuffer

最後に欠けているのは、インデックス バッファです。

//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glVertexArrayElementBuffer(vao, ibo);

これで、vao は古いコードと同じ状態になるはずです。

于 2015-09-23T12:22:28.830 に答える