9

私のコードは正常に動作していますが、偶然かもしれません。後でバグについて詳しく説明したくないので、できるだけきれいに保つようにしています。

メッシュを初期化するために次のことを行います。

  1. VBO とバッファ データの生成とバインド
  2. IBOおよびバッファデータの生成とバインド
  3. VAO の生成とバインド
  4. 1で生成された、前と同じVBOをバインドします。
  5. 必要な頂点属性配列を有効にし、頂点属性ポインターを設定します
  6. IBOを再度バインドします(理由は正確にはわかりません)
  7. 作成したばかりの VAO を台無しにしないように、BindVertexArray を 0 に戻します。

私の理解では、VAO は有効にした頂点属性配列の状態を保存します。また、バインドした VBO と IBO の両方も保存されます。Vertex Array を 0 にバインドして VAO のすべてのアクションを「閉じた」ため、他のコードが私の VAO を台無しにすることはありません。これで問題がなければ、レンダリングする必要があるのは次のとおりです。

  1. バインドVAO
  2. 要素を描く
  3. VAO のバインドを解除 (0 にバインド)

これにより、AttribArray の状態と、保存されている VBO および IBO の両方が表示されます。私の質問は次のとおりです。

A. VertexAttribPointers を設定した後、IBO をバインドする必要がありますか? もしそうなら、なぜですか?

B. VAO は本当にVBOIBO の両方を保存しますか? バインドされた最後のバッファーのみを保存すると聞いたことがあります。つまり、次のようにレンダリングする必要があります。

  1. バインドVAO
  2. VBO をバインド
  3. 要素を描く
  4. VAO のバインドを解除

しかし、これは意味がありません。両方のバッファ オブジェクトを格納しないのに、なぜ VAO を使用するのでしょうか? VBO と IBO をバインドしてから、VAO をバインドせずに要素を描画するのと同じではありませんか?

助けてくれてありがとう。

コードは次のとおりです。

初期化

// generate VBO
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, m_vertices.size()*sizeof(GLfloat), m_vertices.data(), GL_STATIC_DRAW);

// generate IBO
glGenBuffers(1, &m_ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indices.size()*sizeof(unsigned short), m_indices.data(), GL_STATIC_DRAW);

// generate VAO
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);

// set the vertex attribute pointer
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,vertexSize,reinterpret_cast<const GLvoid*>(0));         

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
glBindVertexArray(0);

描く

glBindVertexArray(m_vao);
glDrawElements(GL_TRIANGLES,size,GL_UNSIGNED_SHORT,reinterpret_cast<const GLvoid*>(0));
glBindVertexArray(0);

また、次のようにするとすっきりしませんか。

  1. VAO の生成とバインド
  2. IBO と BufferData の生成とバインド
  3. VBO と BufferData を生成してバインドする
  4. 私が必要とし、VertexAttribPointers を設定する EnableVertexAttribArrays
  5. VAO のバインドを解除 (0 にバインド)

よりきれいに見えますが、特にステップ 4 と 5 の間に IBO バインディングがないため、結果が同じかどうかはわかりません。

4

1 に答える 1

9

質問への対処:

A. VertexAttribPointers を設定した後、IBO をバインドする必要がありますか? もしそうなら、なぜですか?

いいえ。最初に要素配列 (用語では IBO) をバインドし、後で頂点属性を実行することもできますが、一般的に言えば、それらは VAO 内の個別のバインドです。たとえば、IBO と複数の VBO をバインドglDrawElementsし、IBO 内のデータを使用して (およびバリアント)、またはglDrawArraysVBO 内の連続頂点データのみを使用して (およびバリアント) を使用してレンダリングできます。レンダリング コマンドは、 IBO が使用されているかどうか。

B. VAO は本当に VBO と IBO の両方を保存しますか?

はい。VAO は、1 つの IBO と少なくとも 16 の VBO のバインディング情報を格納できます。

バインドされた最後のバッファーのみを保存すると聞いたことがあります。つまり、次のようにレンダリングする必要があります。

VAO の
バインド VBOのバインド
要素の描画VAO の
バインド解除

元の投稿で推測したように、このステートメントは正しくなく、含める VBO のバインドは不要です。VAO は、実装に依存する最大数 (少なくとも 16) の VBO を格納でき、それぞれを頂点属性にバインドできます。

また、次のようにするとすっきりしませんか。

  1. VAO の生成とバインド
  2. IBO と BufferData の生成とバインド
  3. VBO と BufferData を生成してバインドする
  4. 私が必要とし、VertexAttribPointers を設定する EnableVertexAttribArrays
  5. VAO のバインドを解除 (0 にバインド)

はい。ご指摘のとおり、バインド、レンダリング、クリーンアップをたった 3 つのコマンドで実行できます。

本当に、それが VAO の要点であり、これらすべてのバインディングと頂点属性の関連付けを収集して、すべての配管を一度実行し、後で起動して忘れることができるようにします。

于 2013-06-27T07:56:51.040 に答える