OpenGLの頂点配列オブジェクトの目的は何ですか?


36

OpenGLを始めたばかりですが、Vertex配列オブジェクトとは何か、どのように使用できるかをまだよく理解していません。

頂点バッファオブジェクトを使用して頂点データ(位置やテクスチャ座標など)を保存し、VAOにステータスフラグのみが含まれている場合、どこで使用できますか?彼らの目的は何ですか?

(非常に不完全で不明瞭な)GL Wikiから理解した限りでは、VAOは、要素配列バッファーで説明されている順序に従って、すべての頂点にフラグ/状態を設定するために使用されますが、Wikiについては本当にあいまいでしたVAOが実際に何をするのか、そしてどのようにそれらを採用できるのか、本当によくわからない。

回答:


49

サンプルを使用すると、その目的をよりよく理解できると思います。コメントを読むことで、VAOの使用方法を理解できます。

// BEGIN INITIALIZATION
// Define some vertex data 
struct Vertex {
  GLfloat position[3];
  GLfloat texcoord[2];
};
Vertex vertexdata[NUM_VERTS] = { ... };
GLubyte indexdata[NUM_INDICES] = { 0, 1, 2, ... };

// Create and bind a VAO
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

// Create and bind a BO for vertex data
GLuint vbuffer;
glGenBuffers(1, &vbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vbuffer);

// copy data into the buffer object
glBufferData(GL_ARRAY_BUFFER, NUM_VERTS * sizeof(Vertex), vertexdata, GL_STATIC_DRAW);

// set up vertex attributes
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texcoord));

// Create and bind a BO for index data
GLuint ibuffer;
glGenBuffers(1, &ibuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuffer);

// copy data into the buffer object
glBufferData(GL_ELEMENT_ARRAY_BUFFER, NUM_INDICES * sizeof(GLubyte), indexdata, GL_STATIC_DRAW);

// At this point the VAO is set up with two vertex attributes
// referencing the same buffer object, and another buffer object
// as source for index data. We can now unbind the VAO, go do
// something else, and bind it again later when we want to render
// with it.

glBindVertexArray(0);

// END INITIALIZATION

// BEGIN RENDER LOOP

// This is it. Binding the VAO again restores all buffer 
// bindings and attribute settings that were previously set up
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, NUM_INDICES, GL_UNSIGNED_BYTE, (void*)0);

// END RENDER LOOP

2
GL_DYNAMIC_DRAWバッファデータでもこれを実行できますか?レンダリングパーツには、glBindVertexArray()、glBufferData()、glDrawElements()のみが含まれますか?
ピク

この例では法線をどのように扱いますか?GLfloat normal[3]Vertexクラスにを追加し、法線をクライアントにアップロードする場合はどうなるでしょうか。
リネロ

1

すべての属性を毎回設定する必要がないため、VAOは便利です。また、すべての属性を設定するのではなく、1つのVAOをバインドするだけで高速になります。


1

これは私のお気に入りのリンクです:http : //www.songho.ca/opengl/gl_vertexarray.html

VAOとVBOの違いをよりよく理解するのに役立ちます。また、このトピックに関するすばらしいOpenGLの章を読むことをお勧めします。これらの基本を詳細に、例とともに説明するのに適しています。


6
リンクした記事では、VAOについては説明していません。頂点配列(これはもう少し前からありました)についてのみです。私は、この2つの違いを具体的に理解していないのです。
スティーブンルー

大きな違いはありません。VAOは、VBOに格納されている配列データ自体を除き、頂点配列とその使用法と形式に関するすべての状態をカプセル化します。しかし、あなたは、この答え(またはリンク)がVAOについて実際には話していないという点で正しいです。
クリスは、モニカを復活

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.