バッファーのバインドを解除する必要がありますか?


12

OpenGL ES 2でいくつかのテストを行っていますが、いくつか質問があります。私の現在のプログラムは次のようなものです。

Init
-------
-> create index buffer
-> fill index buffer glBufferData 
-> create vertex buffer
-> fill vertex buffer glBufferData 

Draw
-------
 1. Apply vertex buffer

    -> Bind VAO
       -> bind vertex buffer
          - enable attributs (glVertexPointer, …)
       -> unbind vertex buffer
    -> Unbind VAO
    -> Bind VAO

 3. Apply index buffer
 4. Draw

問題

いくつかの研究の後、与えられたコードがクラッシュし、理由を理解しました:init部分でインデックスバッファをバインド解除する必要があります(「インデックスバッファglBufferDataを埋める」後)、または最初の「バインドVAO」の前にバインドを解除します

私の質問は:

  • インデックスバッファをVAO(VAOストックインデックスバッファ)に配置できますか?
  • 更新ごとにバッファのバインドを解除する必要がありましたか(glBufferData)?

私のアプリケーションでは、各フレームで更新されるいくつかのバッファー(例:パーティクル)があるので、そのようなOpenGLスタックがあります。

-> bind buffer 1
-> update buffer 1
-> close buffer 1
-> bind buffer 1
-> draw

最初の3行は、最後の2つの描画オブジェクトであるVertexバッファーを更新します。

-> bind buffer 1
-> update buffer 1
-> draw

ありがとう

回答:


12

あなたは不必要なバインディング/アンバインディングで多くをしているようです。VAOを使用している場合は、VAOのセットアップ時およびジオメトリの描画時にのみVAOをバインドする必要があります。更新する必要がある場合にのみ、VBO / IBOを再度バインドします。

バッファーを描画または更新した後、必ずしもバインドを解除する必要はありませんが、バインドされたままのバッファーへの偶発的な書き込みを避けるためにバインドを解除することをお勧めします。

操作の最初のシーケンスを取得すると、これは私が期待する全体的な順序です。

初期化時:

  1. VAOを作成してバインドします。シーケンスでバインドするVBOおよびIBOは、現在のVAO(これ)に関連付けられます。

  2. インデックスバッファを作成およびバインドします。

    • インデックスバッファをで埋めますglBufferData/glMapBuffer
  3. 頂点バッファを作成およびバインドします。

    • 頂点バッファを埋めglBufferData/glMapBufferます。
  4. glEnableVertexAttribArray/glVertexAttribPointerなどで頂点属性を設定します。

  5. バッファとVAOの偶発的な変更を避けるために、オプションですべてのバインドを解除します。最初にVAOバインド解除することを忘れないでください。例えば:glBindVertexArray(0);

描画時:

  1. バッファーのみを描画する場合

    • VAOをバインドします。
    • 描画呼び出しを実行します。
  2. 更新および描画する場合

    • VAO、VBO、IBOをバインドします。
    • バッファーを更新します(頂点属性の更新は、頂点形式が変更された場合にのみ必要です)。
    • 描画呼び出しを実行します。
  3. オプションで、バッファーとVAOの偶発的な変更を避けるためにバインドを解除します。

それはそれと同じくらい簡単です。この操作の順序は問題なく機能するはずです。


2
私の実験(2014)で実際のケース(GPUでボトルネックにならないシンプルなシェーダー)に追加したいのですが、VAOを使用したパフォーマンスの改善は、適切な順序付けの後では重要ではありません(<2%のCPU節約)連続するレンダリング呼び出しで同じVBOを使用する場合、VBOセットアップを完全にスキップするためにレンダリング呼び出しの実装が実装されました(CPUを10から33%節約します)。また、VAOでドライバーのバグをいくつか見つけたため、デフォルトでオフにしました。複雑なシェーダー、MSAAなどを使用すると、GPUのボトルネックとなり、モバイルでもCPUがアイドル状態で待機することになり、重要性はさらに低下しました。
ステファンホッケンハル14

2
ハードウェアでサポートされていない方法で頂点データを調整しないと、GPUドライバーは各セットアップで VBOデータ並べ替えることになりますが、ドライバーはYMMVが変更されない限り、VAOで1回並べ替えることができます。とにかく頂点データの整列とパディングに最適です。
ステファンホッケンハル14

1
なぜVAOを他のすべての前にバインド解除する必要があるのですか?
ダニエルサファリ

@DanielSafari、セットアップ後ですか?最初にバッファーのバインドを解除した場合(バッファー0 / nullのバインド)、現在のVAO内のそのバインドポイントがクリアされます。そのため、null VAOを最初に設定する必要があります。
-glampert

@glampert-いいえ、それはバインディングの仕組みではありません。バッファーバインディングはglVertexAttribPointerが呼び出されたときに使用され、そうでない場合は使用されません(例外:GL_ELEMENT_ARRAY_BUFFER)。glVertexAttribPointer呼び出し後にバッファーバインディングを変更しても効果はありません。
マキシマスミニマス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.