132

私は今日、このチュートリアルから OpenGL を学び始めたばかりです: http://openglbook.com/the-book/
第 2 章では、三角形を描き、VAO 以外のすべてを理解しました (この頭字語は OK ですか?)。チュートリアルには次のコードがあります。

glGenVertexArrays(1, &VaoId);
glBindVertexArray(VaoId);

コードが必要であることは理解していますが、それが何をするのかわかりません。この時点以降は (破棄する場合を除いて) VaoId を使用したことはありませんが、VaoId がないとコードは機能しません。これはバインドする必要があるためだと思いますが、理由はわかりません。この正確なコードは、すべての OpenGL プログラムの一部である必要がありますか? チュートリアルでは、VAO を次のように説明しています。

頂点配列オブジェクト (または VAO) は、頂点属性が頂点バッファー オブジェクト (または VBO) に格納される方法を記述するオブジェクトです。これは、VAO が頂点データを格納する実際のオブジェクトではなく、頂点データの記述子であることを意味します。頂点属性は、glVertexAttribPointer 関数と、その 2 つの姉妹関数 glVertexAttribIPointer および glVertexAttribLPointer によって記述できます。最初のものについては以下で説明します。

VAO が頂点属性をどのように記述しているかわかりません。私はそれらを決して説明していません。glVertexAttribPointer から情報を取得しますか? きっとこれだと思います。VAO は単に glVertexAttribPointer からの情報の宛先ですか?

ちなみに、私がフォローしているチュートリアルは受け入れられますか? 注意すべきことや、従うべきより良いチュートリアルはありますか?

4

4 に答える 4

114

「Vertex Array Object」は、OpenGL ARB Subcommittee for Silly Names によって提供されています。

ジオメトリ オブジェクトと考えてください。(昔の SGI Performer プログラマーとして、私はそれらをジオセットと呼んでいます。) オブジェクトのインスタンス変数/メンバーは、頂点ポインター、通常のポインター、カラー ポインター、属性 N ポインターなどです。

VAO が最初にバインドされるとき、呼び出してこれらのメンバーを割り当てます。

glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer...;
glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer...;

等々。有効にする属性と指定したポインターは、VAO に格納されます。

その後、VAO を再度バインドすると、これらの属性とポインターもすべて最新になります。したがって、1 回のglBindVertexArray呼び出しは、以前にすべての属性を設定するために必要だったすべてのコードに相当します。独自の構造体やオブジェクトを作成しなくても、関数やメソッド間でジオメトリを渡すのに便利です。

(1 回のセットアップで複数回使用するのが VAO を使用する最も簡単な方法ですが、属性をバインドしてさらに有効化/ポインター呼び出しを行うだけで属性を変更することもできます。VAO は定数ではありません。)

パトリックの質問に対する詳細情報:

新しく作成されたVAOのデフォルトは空です(AFAIK)。ジオメトリはまったくなく、頂点も含まれていないため、描画しようとすると OpenGL エラーが発生します。これは、「すべてを False/NULL/ゼロに初期化する」のように、かなり正気です。

glEnableClientState設定するときだけ必要です。VAO は、各ポインターの有効/無効状態を記憶しています。

はい、VAO は と を保存glEnableVertexAttribArrayglVertexAttribます。古い頂点、法線、色、... 配列は、属性配列、頂点 == #0 などと同じです。

于 2012-08-06T01:24:45.740 に答える
11

頂点配列オブジェクトは、ワープロ プログラムなどのマクロのようなものです。適切な説明はここにあります

マクロは、このアトリビュートを有効にする、そのバッファをバインドするなど、実行したアクションを記憶glBindVertexArray( yourVAOId )するだけです。

したがって、 draw の次の呼び出しでは、VAO によってバインドされたものをすべて使用します。

VAO は頂点データを保存しません。いいえ。頂点データは、頂点バッファーまたはクライアント メモリの配列に格納されます。

于 2013-07-07T22:39:56.693 に答える
7

VAO は、OpenGL パイプラインの頂点フェッチ ステージを表すオブジェクトであり、頂点シェーダーに入力を供給するために使用されます。

このような頂点配列オブジェクトを作成できます

GLuint vao;
glCreateVertexArrays(1, &vao);
glBindVertexArray(vao);

まず、簡単な例をやってみましょう。シェーダーコードでそのような入力パラメーターを検討してください

layout (location = 0) in vec4 offset; // input vertex attribute

この属性を入力するには、次を使用できます

glVertexAttrib4fv(0, attrib); // updates the value of input attribute 0

頂点配列オブジェクトはこれらの静的属性値を格納しますが、さらに多くのことができます。

頂点配列オブジェクトを作成したら、その状態の入力を開始できます。提供するバッファ オブジェクトに格納されているデータを使用して、OpenGL に自動的に入力するように依頼します。各頂点属性は、いくつかの頂点バッファー バインディングの 1 つにバインドされたバッファーからデータを取得します。この目的のために、 を使用しますglVertexArrayAttribBinding(GLuint vao, GLuint attribindex, GLuint bindingindex)。また、このglVertexArrayVertexBuffer()関数を使用して、バッファーを頂点バッファー バインディングの 1 つにバインドします。関数を使用しglVertexArrayAttribFormat()てデータのレイアウトと形式を記述し、最後に を呼び出して属性の自動入力を有効にしますglEnableVertexAttribArray()

頂点属性が有効な場合、OpenGL は、 および で指定した形式と位置情報に基づいて頂点シェーダーにデータをフィードし glVertexArrayVertexBuffer()ますglVertexArrayAttribFormat()。アトリビュートを無効にすると、 への呼び出しで提供する静的情報が頂点シェーダに提供されますglVertexAttrib*()

// First, bind a vertex buffer to the VAO
glVertexArrayVertexBuffer(vao, 0, buffer, 0, sizeof(vmath::vec4));

// Now, describe the data to OpenGL, tell it where it is, and turn on automatic
// vertex fetching for the specified attribute
glVertexArrayAttribFormat(vao, 0, 4, GL_FLOAT, GL_FALSE, 0);

glEnableVertexArrayAttrib(vao, 0);

シェーダーでコード化する

layout (location = 0) in vec4 position;

結局、 に電話する必要がありますglDeleteVertexArrays(1, &vao)


OpenGL SuperBibleを読んで理解を深めることができます。

于 2015-10-14T08:17:18.603 に答える