大まかに言って、答えは「状況次第」です。パーティクルの更新を送信する方法は、一連のGPUスキンモデルを送信する方法とはかなり異なります。
頂点/インデックスバッファー
ただし、一般的な意味では、最近のすべてはVBO(頂点バッファーオブジェクト)で行われます。古い即時モードAPI(glBegin
/ glEnd
)は、ドライバーの内部頂点バッファーシステムのファットラッパーとしておそらく実装されています。
静的オブジェクトの場合は、静的VBOを作成して、頂点データを入力します。いずれかの頂点が共有されている場合(通常はその場合)、おそらくインデックスバッファーも作成する必要があります。これにより、メッシュの変更(転送帯域幅を節約できる可能性がある)と処理(頂点シェーディング時間を節約できる)のために同じデータを複数回送信する必要性が減少します。インデックス付きの描画とインデックスなしの描画を行うときは、異なる関数で描画することに注意してください。
動的オブジェクトの場合は、バッファの動的セットを使用して同じことを行います。
上級ノート
地形のような大きなピースの場合、メッシュを複数のピースに分割することはおそらくないでしょう。特に20万の三角形が表示されているときにGPUが1億の三角形をレンダリングするようにすることは、特にそれらが並べ替えられておらず、オーバードローや無駄なフラグメントシェーダーの呼び出しが多い場合、非常に無駄です。メッシュを大きなチャンクに分割し、視錐台内にあるものだけをレンダリングします。錐台にあるかもしれないが、完全に丘や建物の後ろなどにあるチャンクを取り除くために使用できる、より高度なカリングテクニックもあります。ドローコールのカウントダウンを維持することは良いことですが、ドローコールの最小化と非表示のジオメトリの描画の最小化の間には、バランスを取る必要があります(特定のアプリ/ハードウェアについて見つける必要があります)。
GPUバッファーについて覚えておくべき重要なことの1つは、GPUがバッファーを読み取っている間は、そこに書き込むことができないことです。ドライバーに、バッファーの古いコピーを破棄しても(それが終わったら)いいことを知らせ、新しいものを与える必要があります(古いものがビジー状態の場合)。もちろん、OpenGLがこれを実行するための関数がなかったのは長い間ありました(現在、GL 4.3のInvalidateBufferDataと、拡張機能としていくつかの古い実装があります)。むしろ、ほとんどのドライバが実装する非標準的で一般的な動作があります。更新する前にバッファを破棄するには、次のようにします。
glBindBuffer(GL_ARRAY_BUFFER, my_vbo);
glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_DYNAMIC_DRAW);
もちろん変更GL_ARRAY_BUFFER
してGL_DYNAMIC_DRAW
、バッファの適切な値にます。静的バッファーは更新されない(または更新されるべきではない)ため、そのようなバッファーの破棄について心配する必要はほとんどありません。
を使用する方が速い場合glBufferData
やglBufferSubData
、を使用すると高速になる場合があることに注意してくださいglMapBuffer
。それは本当にドライバーとハードウェアに依存します。現世代のPCハードウェアはおそらく最速ですがglBufferData
、確実にテストしてください。
別の手法は、インスタンス化を使用することです。インスタンス化により、頂点/インデックスバッファーにデータの複数のコピーを描画する単一の描画呼び出しを行うことができます。たとえば、100個の同一の岩がある場合、100個の独立したドローを作成するのではなく、それらをすべて一度に描画することをお勧めします。
インスタンス化するときは、インスタンスごとのデータを別のバッファーに配置する必要があります(各個人のオブジェクトの位置など)。これは、均一バッファー(D3D用語では定数バッファー)、テクスチャバッファー、またはインスタンスごとの頂点属性のいずれかです。繰り返しますが、どちらが速いかは異なります。インスタンスごとの属性はおそらくより速く、間違いなく使いやすいですが、多くの一般的なGL実装はまだサポートしていませんglBindingAttribDivisor
、使用できるかどうか、そして本当に速いかどうかを確認する必要があります(一部の古いドライバーは、追加によってインスタンス化をエミュレートしましたバッファを使用すると、独立した描画呼び出しを行うよりもインスタンス化を使用する方が遅くなり、標準的な方法はありません... OpenGLを使用する喜び)。
頂点キャッシュ最適化のアルゴリズムもあります。これは、バッファ内の頂点/インデックスを順序付けして、最新のGPUの頂点キャッシュで意志を再生する動作です。GPUは頂点のシェーダーのみを実行してから、頂点キャッシュにキャッシュしますが、他の頂点のためのスペースを確保するには、早めに排除する必要がある場合があります。(たとえば、2つの三角形はどちらも頂点を共有していますが、それらの間に100個の三角形が描画されています。共有された頂点は、おそらく頂点シェーダーによって2回無駄に評価されることになります。)
これらの機能のいくつかは、GLまたはGLESの新しい十分なバージョンを必要とします。たとえば、GLES2はインスタンス化をサポートしていませんでした。
常にプロファイル
繰り返しになりますが、パフォーマンスを重視する場合は、可能な各方法をテストし、ターゲットハードウェアでのアプリの方が速い方法を確認してください。異なるメーカーの異なるハードウェア/ドライバーが異なるだけでなく、ハードウェアのクラス全体が本質的に異なる場合があります。典型的なモバイルGPUは、典型的な個別のデスクトップGPUとは非常に異なる獣です。「最高」のテクニックは、必ずしも別のベストではありません。
パフォーマンスに関しては、常に懐疑的です。