遅延シェーディングレンダラーのジオメトリパスの一般的なレンダリング最適化手法は何ですか?[閉まっている]


16

OpenGL 3とC ++(およびウィンドウ管理用のglfw)を使用してゲームエンジンを開発しています。私はこれまでに進めてきましたが、サウンドエンティティと最適化以外のほとんどのことは完了しています。エンジンは遅延シェーディングを使用しているため、遅延シェーディング自体は平均的なGPUにとって疲れるプロセスなので、レンダリングプロセスを可能な限り最適化したいと思います。

現在のシステムは、レンダラーと現在のワールドを含むシーンで構成され、ワー​​ルドはエンティティとライティングエンティティを別々に保持しstd::vectorsます。

そのため、基本的にSceneが呼び出されるたびに->render()、Rendererを呼び出し、ワールドをパラメーターとして渡し、ワールドからエンティティイテレーターを取得し、FBOにそれらを描画してから、2番目のパスのライティングエンティティを通過します。そして、これは十分ではないと思います。

現在のアルゴリズムは、エンティティが画面スペースにない場合でもすべてを繰り返し処理します。現在のレンダリングアルゴリズムを最適化して、可視オブジェクトに対してのみAPI関数を呼び出す方法を考えています。そのようなレンダラーを最適化する一般的な手法は何ですか?

回答:


41

遅延シェーディングは、後の段階で実際のシェーディング操作を「延期」するための手法にすぎません。これは、10パスを必要とする10個のライトをレンダリングするために必要なパス数を減らすのに役立ちます。私のポイントは、使用しているレンダリング手法に関係なく、レンダリングパイプラインで処理する必要のあるオブジェクト(頂点、法線など)の数を減らす特定のレンダリング最適化があります。

レンダリングの最適化のための事実上の標準はありませんが、特定のパフォーマンス特性を達成するために交換可能または一緒に使用できる多くのテクニックがあります。各手法の使用は、レンダリングされるシーンの性質に大きく依存します。

遅延レンダリングは、ライトの数が増えると問題を解決しようとします。これにより、フォワードレンダリングではパスの数が爆発する可能性があります。

これらの手法は、遅延シェーディング部分を直接最適化しませんが、説明によると、遅延シェーディング部分は問題ではありません。ただし、あなたの問題は、シーン全体をレンダリングパイプラインに送信することです。そのため、結果をgバッファに送信できるようにするために、エンジンはシーン内で処理する必要があります(たとえば、1億個の頂点すべて)。これらの1億個の頂点のほとんどは、前処理頂点とフラグメントが通過します。

フォワードレンダラーの場合、N頂点は、頂点ステージによって合計で処理さvertex count*lights countれ、フラグメントステージによって合計で処理されますfragments count*number Lights。遅延シェーディングは、これを解決する前にvertex count、頂点ステージとfragments countフラグメントカウントに対してのみ効果的に削減します。実際のシェーディング。しかし、Nを処理するには多すぎる場合があります。特に、それらのほとんどを簡単に選別できる場合はなおさらです。

これにより、フォワードレンダリング/複数パスの場合にカリングがより効果的になります。ただし、ほとんどのエンジンはデュアルレンダリングアプローチを使用することに注意してください。遅延シェーディングだけでは透明なオブジェクトを解決できないため、これらの最適化を使用する必要があります。すべてを実行しない商用エンジンは知りません。

錐台カリング

ビュー錐台に完全または部分的に含まれるオブジェクトのみが、レンダリングパイプラインに送信される必要があります。これは錐台カリングの基本概念であり、残念ながらメッシュが視錐台に出入りするかどうかを確認するのは高価な操作になる可能性があるため、代わりにエンジン設計者は(AABB)Axis Alignedバウンディングボックスまたはバウンディング球のような近似バウンディングボリュームを使用します、これは実際のメッシュを使用するほど正確ではないかもしれませんが、精度の違いは実際のメッシュで確認する手間をかける価値はありません。

ここに画像の説明を入力してください

境界ボリュームを使用しても、実際に各ボリュームをチェックする必要はありません。代わりに、境界ボリューム階層を構築して以前のカリングを実行できます。これを使用すると、シーンの複雑さに大きく依存します。

これは、より小型のエンジンに適したシンプルな手法であり、これまで使用したすべてのエンジンでほぼ使用されています。エンジンで非常に複雑なシーンをレンダリングする必要がない場合は、階層なしで「通常の」境界ボリューム/錐台チェックを使用することをお勧めします。

境界ボリューム階層

背面カリング

これは必須です、とにかく見えない顔を描くのはなぜですか?レンダリングAPIは、背面カリングのオン/オフを切り替えるインターフェースを提供します。特定の状況で背面を描画する必要がある一部のCADアプリケーションのように、オンにしない強力な理由がない限り、これは必須のことです。

オクルージョンカリング

Zバッファを使用すると、可視性の決定を解決できます。しかし、問題は、Zバッファーはパイプラインの後の段階でしか解決できないため、Zバッファーのパフォーマンスが常に優れているとは限らないことです。 Zテストに失敗する前のカラーバッファー。

オクルージョンカリングは、レンダリング錐台にあるオクルードされたオブジェクトをカリングするためにいくつかの初期テストを行うことにより、これを解決します。オクルージョンカリングの実用的な実装の1つは、ポイントベースのクエリを使用して、特定のオブジェクトが特定のポイントビューから見えるかどうかを確認することです。これは、最終イメージに寄与しないライトをカリングするためにも使用できます。これは、遅延エンジンレンダラーで特に役立ちます。

ここに画像の説明を入力してください

このような手法の実例としては、GTA5があります。GTA5では、摩天楼が都市の中心に戦略的に配置され、装飾だけでなく、オクルーダーとしても機能し、都市の残りの部分を効果的に塞ぎ、ラスタライズ。

LOD

詳細度

詳細レベルは広く使用されている手法であり、メッシュがシーンにあまり寄与していない場合に、よりシンプルなバージョンのメッシュを使用するという考え方です。2つの一般的な実装があります。大きく貢献しなくなった場合、単純にメッシュを単純なものに切り替えるだけです。メッシュは、距離やメッシュが占めるピクセル数(画面上の領域)などの要因に基づいて選択されます。もう1つのバージョンはメッシュを動的にテッセレーションします。これはテレインレンダリングで広く使用されています。

ここに画像の説明を入力してください

これらのすべてが機能しなかった場合はどうなりますか?

まあ、それは良い質問です。

最初に行う必要があるのは、グラフィックスプロファイラーを使用してアプリケーションのプロファイルを作成し、ボトルネックがどこにあるかを判断することです。レンダリングされるコンテンツが変更されると、ボトルネックが変わる可能性があることに注意してください。ボトルネックもCPUで実行されるコードの一部である可能性があるため、それも測定する必要があります。

その後、ボトルネックの最適化を行う必要がありますが、これには正しい答えはなく、ハードウェアごとに異なることに注意してください。

一般的なGPU最適化のコツ:

  • シェーダーでの分岐を避けます。
  • たとえば{VNT}、同じ配列または{V},{N},{T}異なる配列でインターリーブされた異なる頂点構造を試してください。
  • シーンを前面から背面に描画します。
  • たとえば、画像がZテストを必要としない場合、いくつかのポイントでZバッファをオフにします。
  • 圧縮テクスチャを使用します。

一般的なCPU最適化のコツ:

  • 小さな関数にはインライン関数を使用します。
  • 可能な場合は、SIMD(単一命令複数データ)を使用します。
  • キャッシュが不親切なメモリジャンプを避ける。
  • 「適切な」量のデータでVBOを使用します。(ハードウェアによって異なります)が、通常は描画呼び出しは少ない方が良いです。

しかし、ボトルネックが遅延シェーディングにあった場合はどうでしょうか?

この場合、遅延シェーディングはライトに関心があるため、最も明白な部分は実際のシェーディング計算を最適化することです。注目すべきポイントのいくつか:

  • 最終画像に実際に影響するライトをレンダリングします。言い換えると、寄与しないライトをカリングします。これは、前述のオクルージョンカリングを使用して効果的に実装できます。
  • このライトには鏡面反射光またはその他のコンポーネントが必要ですか?そうでないかもしれない。
  • この光は影を落としますか?一部のライトは、影を落とす必要がありません。
  • この軽い寄与は事前に計算できますか?動いていない場合、おそらくいくつかの側面を事前に計算できます。

申し訳ありませんが、これらは遅延シェーディングとは何の関係もありません。実際には、テクニックが効果的に軽減する正確なパフォーマンスの問題であり、したがって、実行するのに最も有用な最適化ではありません。支配的な時間を取って、遅延シェーディングはおそらく間違った選択です。
MickLH

@MickLH残念ながら、どうやら質問を読んでいないようです。彼の問題は主に、シーン全体を毎回繰り返すことであり、シェーディングの遅延に関するボトルネックについては言及していません。最初に、多くのライト/マテリアルがある場合、遅延シェーディングがパス爆発問題を解決することを述べました。しかし、その後、これらは、シェーディングテクニックが前方または後方に関係なく、すべてのエンジンにとって必須の最適化であると付け加えました。これらは技術がまねる正確な問題であることに強く反対しますが、ここではすべてのポイントに取り組むことはできません(以下)
concept3d

たとえば、錐台カリングなしで遅延エンジンを構築するのは本当に愚かです。そのため、エンジンは、結果をg-bufferに送信するためだけに(たとえば1億頂点)処理します。異なるシェーディングは、彼の問題ではなく、すべてのジオメトリをパイプラインに送信するという彼の問題ではない、別の問題を解決します。
concept3d

ただし、照明の計算で最適化を行う必要があるという点では同意しますが、光の計算が支配的ではない場合、延期は間違った方法です。しかし、これも彼の問題ではありませんでした。
concept3d

パフォーマンスの問題が遅延シェーディングとは無関係であることを彼/彼女とグーグルに示していないので、これらの最適化が実際に遅延レンダラーにとって最も効果が低いことを明確にした場合、ダウン投票を撤回します。
MickLH

6

問題はシェーディングの遅延とは関係ありません。特定の部分を高速化する前に、レンダラーの基本的なコア要素を実装する必要があります。

concept3dの説明を終えたら、(ラスタライズパス全体ではなく)遅延シェーダー自体を最適化する必要があることが実際にわかった場合は、タイルベースの遅延シェーディングを実装できます。

ダイナミックライトの数に制限されない場合は、遅延シェーディングをまったく使用しない理由を検討する必要がありますが、その場合、Battlefield 3を可能にした最適化を試してください。(彼らは公開PDFのスライド10でそれを示唆していますhttp : //dice.se/wp-content/uploads/GDC11_DX11inBF3_Public.pdf

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