大きな頂点バッファーと複数の描画呼び出し


14

OpenGLを使い始めたばかりで、それを使用して2Dゲームを作成しようとしています。このゲームでは、非常に多くのさまざまな色の六角形で構成される六角形のグリッドがあります。初心者のOpenGLプログラマーとして、このグリッドを描くには2つの方法があります。

  1. 単一の六角形のデータで頂点バッファーを使用し、均一なオフセット値を使用してCPUを反復処理し、グリッドができるまで同じプログラムを何度も描画します。
  2. 1回の呼び出しですべての六角形を描画する、非常に大きな事前計算済みの単一の頂点バッファーを作成します。

最も効率的な方法は何ですか?これを行うより良い方法はありますか?


事前に計算された頂点バッファーは、画面を1つの六角形だけ超えて拡張する必要があります。その後、完全に六角形になるまでスムーズにスクロールし、そのシナリオの色のように「反り返る」ことでそれを偽造できますGPU上の2Dテクスチャを頂点シェーダーで読み取り、フラグメントシェーダーにフラット補間します。
MickLH

パスは通常、1つのレンダリング操作が前の操作の結果に依存する状況を指します。この質問であなたが尋ねていることは、実際には、単一パス内の描画呼び出しの数を減らすことに関連しています。私はそれがつまらなく聞こえるかもしれませんが、違いを理解することは非常に重要です。さもないと、マルチパスアルゴリズムはあまり意味がありません;)
アンドンM.コールマン

@ AndonM.Colemanうーん、おかげで、私は明らかにグラフィック用語に精通していない。それで、この場合、どのように説明しますか?複数のシェーダー/プログラム呼び出し?
アレクシスキング

順序依存性がないため、これがシングルパスアルゴリズムであることがすぐにわかります。これらの六角形を任意の順序で描画しても、同じ結果が得られます。あなたはかかるかもしれません複数の描画呼び出し、それらをレンダリングするために必要なデータとOpenGLを供給するのが、OpenGLは依存関係が存在しないため、並行して、それらすべてを描くために効果的に自由です。それがあった場合は、マルチパス、それが描画される前に六角Bは、六角Aの結果が必要な場合があります、またはあなたが同じ六角形の複数回描画し、その結果を結合する必要がある場合があります。
アンドンM.コールマン

回答:


9

実際、このようなグリッドを作成する方法はいくつかあります。

最も効率的な方法はインスタンス化です。このようにして、VBOで六角形を1回だけ作成し、これを100、1000、または100万回レンダリングします。ポイント1で述べたように、ユニフォーム付きのシェーダーを使用して手動で行うことができますが、組み込みのOpenGL機能もあります。そのためには、glDrawElementsInstancedを見てください。

インスタンス化されたオブジェクトを一定量以上描画する場合、インスタンス化は他のメソッドよりも高速であることに注意してください。たとえば、1つの大きなVBOを使用すると300の描画が高速になりますが、インスタンス化されたレンダリングを使用すると200万の描画が高速になります。

インスタンス化されたレンダリングを使用する場合、Attribute Divisorsを使用してオブジェクトごとのデータを送信できます。あなたの場合、位置と色を送信したいと思うでしょう。

インスタンス化されたレンダリングに関する優れたチュートリアル:クリック

本当に最善の方法は、両方の方法を試して、1フレームを描画するのにかかるミリ秒数を確認することです。この方法では、両方の方法も学習しますが、常に良い方法です。

また、インスタンス化されたレンダリングは最新のOpenGL機能であり、使用するにはシェーダーを使用する必要があることに注意してください。ただし、最初から正しい方法で学習することが常に最善です。


2
インスタンス化は必ずしも最も効率的ではありません。私のプロファイルを見た多くの実装では、インスタンス化のサポートが適合のために追加されましたが、多くのオブジェクトを個別に描画するよりも遅くなりました(実際、それを行うドライバの実装が不十分なループであった可能性があります)。これはオプションであり、良い方法ですが、「最も効率的」という前提を立てる前に、ターゲットOS /ハードウェアでプロファイリングとテストを慎重に行う必要があります。
ショーンミドルディッチ

同意した。たとえば、Windows / LinuxとAti / nVidiaで異なるパフォーマンスを見てきました。追加していただきありがとうございます。
バサー

1
実際には。単一のvbo内で複数の結合メッシュを描画する場合(同じスペースを共有する)。インスタンス化を高速化する方法はありません。インスタンス化の問題は次のとおりです。頂点は並列計算されたクロスインスタンスではありません。gpu / cpu / gpu sync / drawcallのみが削除されます。したがって、1000個の球体を含む1つの頂点バッファーを描画する方が、ハードウェアインスタンス化で1000個の球体を描画するよりも高速です。(錐台カリング/オブジェクト距離の詳細の最適化は含まれていません)
ジェロンファンランゲン

3

方法1はコーディングが簡単で、一度に表示される六角形が多すぎない限り問題ありません。OpenGLを初めて使用する場合は、これを使い続けることをお勧めします。一度にプレートが複雑になりすぎないようにするためです。

一度に多数の六角形(数百または千以上)が表示されている場合、非常に多くの個別の描画を行うCPUオーバーヘッドを回避するために、オーバーヘッドの少ない方法が必要になります。方法2はこのために機能しますが、インスタンス化を使用することもできます。インスタンス化は、すべてのインスタンスの頂点データの(はるかに大きい)バッファーではなく、インスタンスごとのデータのバッファーを更新するだけでよいため、方法2よりも高速であるか、確実に悪化することはないでしょう。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.