多数の同じオブジェクトを描画するための最も効率的な方法ですが、変換は異なります


8

多数(数千)の単純なメッシュ(多分...最大で50の三角形ですが、それでも非常に大きな上限)を描画したいと思います。これらはすべてまったく同じです。

単純な力ずくの方法として、今は何千もの描画呼び出しを行っています。シェーダーが必要とする変換行列を変更してから、同じオブジェクトをもう一度描画します。

もちろん、これはひどく遅いです。(私が推測しているように)ドライバーと私のPCの描画呼び出しが多すぎて効率的に処理できないためです。

それを速くするために私は何ができますか?


4
私はあなたに完全な答えを与えることはできませんが、高レベルの答えはジオメトリインスタンス化を使用することです
セスバティン2013

グーグルで「Geometry Instancing」を検索すると、その方法に役立つものが見つかる可能性があります
Luis W

回答:


11

これに対する解決策はインスタンス化です。このチュートリアルでは、インスタンス化のいくつかの方法を説明します。ARB_draw_instancedおよびがある場合は、ARB_instanced_arraysそれらを使用してください。

一般的なアイデアは、メッシュのすべての変換を別のバッファーオブジェクトに格納し、それをインスタンスごとに1つの「頂点」を使用する属性配列にバインドすることglVertexAttribDivisorです。

その後も、必要な速度で実行できない場合は、頂点プロセッサにバインドされている可能性があります。メッシュで錐台カリングを実行し、すべてのメッシュで個別にカリングするのではなく、トラバースするBVHを構築することをお勧めします。


1
+1; 何千ものオブジェクトを使用すると、変換でCPUにバインドされる可能性があります(インスタンスごとのバッファーで位置と回転を送信し、GPUでオブジェクトごとの行列を計算するだけでも役立ちます)。その方法を確認することを忘れないでください。あなたはその動的な頂点バッファを更新します!
Maximus Minimus 2013

@Robert Rouhani:ありがとう、私はそれを調査し、すぐに実装しました。これで、250 FPSでそれぞれ20トリスの5000メッシュを描画できます。ところで、あなたの提案した方法は少し時代遅れのようです。OpenGL 3.somethingジオメトリのインスタンス化はOpenGLコア仕様の公式の部分なので、ARB_xxxは不要です。行列を格納するために均一なバッファを使用し、glDrawElementsInstancedを使用します。頂点シェーダー内には、layout(std140)均一行列があります{mat4 array [5000]; array [gl_InstanceID]を介して関連要素にアクセスできる場所
TravisG

1
@TravisG古いバージョンを試してサポートする傾向があります。両方の拡張機能がしばらくコアに昇格されたことを理解していますが、拡張文字列は引き続き存在しますが、:) また、glVertexAttribDivisor(非推奨でも古くなったわけでもありませんが)使用すると、インスタンス数に上限がないという利点があります。パフォーマンスは歴史的に均一バッファーよりも優れていますが、おそらく現在は同じか非常に似ており、両方の方法で仕事を完了できます。
Robert Rouhani 2013

@ロバート・ルーハニ:うーん...それは本当だと思います。古いドライバを使用している人はARB_xxxをサポートできますが、OpenGl 3.xの公式コア機能はサポートできません。おかげで、glVertexAttribDivisorを見てみましょう。
TravisG 2013

@Robert Rouhani:私は両方のバージョンを実装し(均一なバッファーを使用し、代わりに、インスタンスごとに1回だけ変更する頂点属性を使用する推奨バージョン)、均一なバッファーのバージョンは実際には約2倍高速です(リリースモードでは4000 fps、 glVertexAttribDivisorでの〜2000と比較すると、250 fpsの数値はCPU側のみでした)。
TravisG 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.