Skip to content
Go back

A Primer On Efficient Rendering Algorithms & Clustered Shading

· Updated:

web

拙訳

  • 技術的な注目点:不要なピクセルシェーダー実行の省略、または、ライティング計算の数の削減
  • Forward Shadingとは:
    • メッシュとライトの組み合わせごとにドローコール1つを発行し、結果を加算的にブレンドしていく手法
  • Forward Shadingの欠点:
    • シェーダー数の組合せ爆発が起こる
    • シェーダー切り替えに伴うオーバーヘッド
    • メッシュの読み出しを繰り返し行うことによる帯域消費
    • 重ね描き(オーバードロー)すると、すでに描かれたピクセル分の計算が無駄になる
  • Deferred Shadingとは:
    • 可視性を解決しつつ属性をバッファに格納して、後に、そのバッファを使ってライティングを行う手法
      • 属性を格納するバッファをG-Bufferと呼び、位置、法線、アルベド、ラフネスなどを格納する
    • 計算量と帯域幅のトレードオフが可能になる
    • ライティングで頂点を用意しなくて良いので、その分のコストが削減できる
    • ライティングのシェーダーを統合したり分割したりできる
  • Deferred Shadingの欠点:
    • 半透明を取り扱えないので、別にForward Shadingで描画する必要がある
    • ハードウェアベースのMSAAを取り扱えないが、最近はTAAがあるのでなんとかなる
    • Gバッファの構成がシェーディングモデルと紐づくので、たくさんのシェーディングモデルを一挙に扱うのは(Gバッファを大きくするか間接参照を入れるかする)コストがかかる
    • 何より、帯域幅とメモリの大幅な消費が一番のボトルネックになる
  • Tile-based Shadingとは:
    • 画面を2次元に分割したタイルごとに、その範囲内に影響を与えるライトを収集して、そのライトのみでライティングを行う手法
    • ライトをカリングするだけなので、ForwardでもDeferredでも使える
    • 距離による光の減衰から光源の実質的な影響範囲を設定することで、計算に不要なライトを省略することができる
  • Tiled-based Shadingの欠点:
    • 奥行きの離れた物体が同じタイル内に存在すると、ピクセルに寄与しないライトによる計算が行われてしまう
      • 深度の不連続性depth discontinuityという
  • Clustered Shadingとは:
    • 視錐台を3次元に分割したクラスタごとに、その範囲内に影響を与えるライトを収集して、そのライトのみでライティングを行う手法

Clustered Shadingの実装方法

  • 視錐台を縦・横・奥行き方向で分割して、それをクラスタとする
    • 縦横方向の分割はタイルのときと同様でグリッドにする
    • 奥行方向の分割はいくつか方法があるが、うまくいかないものもある
      • NDC空間で均一に分割すると、遠くのクラスタが大きすぎてダメ
      • ビュー空間で均一に分割すると、近くのクラスタが大きすぎてダメ
    • 原論文では、自己相似となる指数関数的な方法で奥行方向を分割する
    • DOOM (2016)では、Z=Nearz(Farz/Nearz)slice/numSlicesZ = Near_z (Far_z / Near_z)^{slice / numSlices}で奥行方向を分割する [Sousa and Geffroy 2016Sousa, T. and Geffroy, J. 2016. The Devil is in the Details: idTech 666. Advances in Real-Time Rendering in Games course. ACM SIGGRAPH. https://advances.realtimerendering.com/s2016/.]
      • 計算は、変数がZのみであり、logとMADの簡単な演算で求められる
    • 分割数はお好みで
    • クラスタのバウンディングボックスは、高速化のため、AABBで近似する
  • 任意:有効なクラスタを特定する
    • Z-Prepassが必要なので、ところ構わず使えるわけではない
    • 深度値を使って、可視である物体の表面が存在するクラスタをマークする
    • 有効なクラスタのみにリストをコンパクト化する
  • ライトをカリングする
    • ライトの影響範囲を包むボリュームとクラスタのAABBとの接触判定を取る
    • 有効なライトは一旦ローカルで列挙して、総数をアトミック変数に加算することで、light index listの領域の割当を行う
    • ライトのデータは以下の構造で格納する
      • シーンのすべてのライトを事前に格納してあるglobal light list
      • クラスタ内で有効なライトのインデックスの配列を格納するlight index list
      • クラスタごとにlight index listのスパンを参照するためのlight grid

最適化