Skip to content
Go back

拙訳「Volumetric Fog: Unified compute shader based solution to atmospheric scattering」

· Updated:

[Wronski 2014Wronski, B. 2014. Volumetric Fog: Unified compute shader based solution to atmospheric scattering. Advances in Real-Time Rendering in Games course. ACM SIGGRAPH. https://advances.realtimerendering.com/s2014/.]

slides web

プレゼンテーションの概要#

  • 大気散乱atmospheric scatteringのイントロダクション
  • 既存のゲームの解法
  • アルゴリズムの概要
  • 実装の詳細
  • …Assasin’s Creed 4の先へ

大気散乱#

  • 空の色
  • フォグ
  • “ゴッドレイ”
  • ライトシャフト
  • ボリューメトリックシャドウ

ゲームにおける大気散乱#

  • 現実感のあるレンダリングのために必要とされる
  • 距離差を知覚するのに役立つ
  • LODやストリーミングを隠すのに役立つ
  • 雰囲気moodや大気を作る
  • “特殊な”効果のために使われるアートの道具

大気散乱#

大気散乱の現象はいずれかの輸送媒質transporting mediaを形成する粒子particlesとフォトンの相互作用によって引き起こされる。光がいずれかの空でない媒質を横断するtraverseとき、フォトンまたは光線light raysはそのような媒質を作り出す粒子と衝突するかもしれない。衝突では、これらは衝突して拡散diffuse吸収absorbかのいずれかが行われるかもしれない(そして、熱エネルギーに変換される)。光学において、そのような処理は通常では統計的にモデル化され、我々は以下の処理に加わるエネルギー量を定義することができる。

  • 透過transmission
  • 散乱
  • 吸収absorbtion

エネルギーは常に保存されるので、我々は以下と記述することができる。

Lincoming=Ltransmitted+Labsorbed+LscatteredL_{\text{incoming}} = L_{\text{transmitted}} + L_{\text{absorbed}} + L_{\text{scattered}}

散乱なし#

光散乱なし/非関与輸送媒質non-participating transport media

我々は輸送媒質が真空のように振る舞うと仮定する --- オブジェクト間の光路上で放射輝度の損失および利得はない。

典型的なレンダリングシナリオ --- 光源からの光が一方のオブジェクトからもう一方へ表面のBRDF関数に従ってバウンスして、最終的にカメラ/目に到達する。

最も単純なあり得るケースはバウンスする光/GIがない、単なる直接ライティングである。

光の散乱#

媒質が光輸送に関与するとき、フォトン/光線に影響を与えるのに十分なほど大きいすべての粒子は光輸送の等式に加えられる。

例えば、塵や水の粒子は光線/フォトンを無作為な方向にバウンスさせ、いくつかの光を光路に侵入させる(in-scattering)。

また、その一方で、いくつかの光はバウンスして脱出するので、光路を外れ、より暗くなる(out-scattering)。

一目瞭然だが、現実では、すべての粒子が位相関数phase functionsに従っていくつかの光に対してout-scatterおよびin-scatterの両方を行うので、これらは非常に複雑である。つまり、複数のレイが光路を何回も出たり入ったりする。しかし、通常、リアルタイムレンダリングでは、多重散乱multiple scatteringを無視しなければならない。

Beer-Lambertの法則#

光の散乱の計算に非常に有用である物理法則は入射光の消散extinction(光のout-scattering)を説明するBeer-Lambertの法則である。この法則は透過率(与えられる方向からの入射光に対する媒質を通って輸送される光の割合)の値を定義する。通常では以下のように定義される。

T(AB)=eABβe(x)dxT(A \to B) = e^{-\int_A^B \beta e(x) dx}

記号βe\beta eは消散係数であり、散乱係数と吸収係数の合計として定義される。我々は、与えられた媒質における光の伝わるtravelled距離の指数関数が光の消散である、ということをBeer-Lambertの法則から確認できる。

異なる散乱の種類#

媒質の粒子に依存して、これらの処理に加えられる光の量は異なり得る。散乱モデルの例のひとつはRayleigh散乱である。これは(空気の粒子のような)非常に小さな粒子の散乱であり、空の青色の原因であるresponsible for。これは非常に等方的で一様であるが、波長依存である --- 散乱は波長が短いほど強く、吸収は無視できる。

一方で、(エアロゾルや塵のような)より大きな粒子のいわゆるMie散乱は強力な前向きのローブstrong forward lobeを伴う非常に異方的な形状やさらにより高い吸収率を持つ。

位相関数#

方向T(α)T(\alpha)に散乱する光位相関数は非常に複雑になり得る
エネルギー保存例:雲の位相関数

| 02π0πP(θ)dθdφ=1\int_0^{2\pi} \int_0^\pi P(\theta) d\theta d\varphi = 1

| 情報源: Bouthors et al. “Real-time realistic illumination and shading of stratiform clouds” |

位相関数はすべての方向における光の散乱量を説明する関数である。

これは光ベクトルと出射方向ベクトルとのなす角の関数である。

これはエネルギー保存の特性を持つ。つまり、すべての方向の積分は1と等しく(、または、そこに焼き込まれた吸収に関する情報を含む場合は1以下となら)なければならない。

いくつかの位相関数は非常に複雑であり、様々なモデルや現実のキャプチャされたデータから説明される可能性がある。

解析的位相関数#

Henyey-Greensteinの位相関数

  • 可変の異方性ファクタ
  • 解析的ライトに対する小さな計算コスト(ほとんど事前計算される)
  • 球面調和関数への自明な拡張
  • Zonal Spherical Harmonics (1,g,g2,g3)(1, g, g^2, g^3)
p(θ)=14π1g2[1+g22gcosθ]3/2p(\theta) = \frac{1}{4\pi} \frac{1 - g^2}{[1 + g^2 - 2g\cos\theta]^{3/2}}

Mieのような異方的な散乱をシミュレートする最も一般的な位相関数はHenyey-Greensteinの位相関数である。これは数々の利点を持つ --- 実行時に計算するのが効率的であり、球面調和関数へ自明に拡張し、可変の異方性ファクタをサポートする。

いくつかのより複雑な位相関数は複数のHenyey-Greensteinの位相関数の加重和weighted sumから構築できる。

散乱の異方性#

ゲームでの近似#

  • 解析解(単純な媒質密度関数)
  • ビルボード/パーティクルベース

ゲームでは、異なる大気および散乱現象は多くのアプローチを用いて近似された。

90年代以降に使われた最初のものと初期のOpenGL仕様は解析解である。最初の近似は非常に単純な深度ベースのフォグを使った。

前世代のコンソールでのフォグレンダリングの最新技術は解析的で指数関数的な距離ベースのフォグであった。これは”Real-time atmospheric effects in games revisited”のプレゼンテーションにおいてWenzelが非常に上手く説明してくれた。これは現実の散乱現象に基づいており、それに対する解析解をもたらす --- ただし、残念ながら、変化する媒質密度とシャドウイングを扱わない。

第二の、恐らく最も使いやすい(それほどプログラマのサポートを必要としない)ものは、(カメラとの交差でのフェードアウトを伴う)アーティストが制作した、カメラの正面を向くビルボードまたはパーティクルである。このアプローチは、アーティスト依存であり、セットアップするのが退屈であり、堅牢でなく(例えば、時刻変化time of dayがあるとき、ある角度では回転が”誤っている”ように見え得る)、十分に動的でない(ライティングやシャドウイングにおける変化に適切に反応しない)、という明確な欠点を持つ。

ゲームでの近似#

  • ポストエフェクトベース
  • レイマーチング

UE3やCryEngineのために人気を得た第三のアプローチはポストエフェクトであり、放射ブラーベースのスクリーンスペースエフェクトである。これは非常に効果的に見える可能性があるが、残念ながら、光源がスクリーン上に見えないときに完全に消失する。

最後に、レイマーチングの解法がある。これらは(特にepipolarサンプリングの拡張機能extension付きで)非常に上手く機能するが、通常は、極短距離用であり、制限を持つ --- 次のスライド。

なぜ2Dレイマーチングでは駄目なのか?#

  • 通常、物理ベースではない
  • ループはGPUの並列性を十分に用いないpoorly uses
    • サンプルは、並列にではなく、直列にsequentially計算される
  • epipolarサンプリングのような解法は制約を受ける
    • 変化する媒質密度を持てない
    • 複数の光源を持てない
  • フォワードシェーディングと互換性がない
    • エフェクトの単一層、情報は1つの深度に対して格納される
    • 低解像度でのエッジのアーティファクト

レイマーチングのボリューメトリックシャドウは、複数の他のタイトルで使われ、最も大きなビジュアル上の改善をもたらし得ることから、最もモダンな解法のように思えた。しかしながら、我々は通常の2Dレイマーチングのいくつかの制限に気付いた。

  • これらの実装のほとんどは近距離close rangeの”ボリューメトリックシャドウ”/“ライトシャフト”のためのものであり、本物の物理ベースではなく、長距離のフォグをサポートするのには適さない。これらは単にアーティスト固有のブレンディングモードをしばしば用いる。
  • これらはループで計算を行っており、モダンなGPUでは逆効果counter-productiveとなる。特に何千ものthread wavesを起動できるAMDのGCNのようなモダンなアーキテクチャでは、GPUパワーの大きな無駄である。これは通常、高解像度のシャドウマップから情報をフェッチするということであり、ここではレイテンシの隠蔽が利益をもたらす可能性がある。
  • epipolarサンプリングのような最近人気を得ているいくつかの賢い最適化は、媒質密度を変化させられない、複数の光源を扱えない、といった多くの制約/制限の下で機能する。すべての異なる光源は異なるepipolarサンプリングスキームを必要とする。
  • 最後に、すべての最新の実装はポストエフェクトとして設計され、透明物transparenciesやパーティクルのようなフォーワードシェーディングされるオブジェクトを適切に扱わなかった。
  • すべてのモダンなレイマーチング実装はより低解像度で機能する。通常、信号は低周波であり、平坦な表面では大きな問題にならないが、回避し辛いアンダーサンプリング、エイリアシング、エッジのアーティファクトを生み出す。

インスピレーション#

Kaplanyan, “Light Propagation Volumes”, SIGGRAPH 2009

[Kaplanyan 2009Kaplanyan, A. 2009. Light Propagation Volumes in CryEngine 3. Advances in Real-Time Rendering in Games course. ACM SIGGRAPH. https://advances.realtimerendering.com/s2009/.]

数々の”典型的”な技術のプロトタイピングの後、我々の最も大きなインスピレーションはSIGGRAPH 2009にて提示されたAnton Kaplanyanによる”Light Propagation Volumes”のGI技術に由来する。

技術のまとめと今後の研究の章で、著者は関与媒質の光輸送を計算するためにlit volumetric texture --- GIをシミュレートするための注入injecting伝播propagatingの結果 --- を使うことに言及している。

これは、光源の数に依存せずにレイマーチングを1回だけ行えば良い、という利点を持つ。関与媒質中の光輸送全体は統一できる。我々は、単純なシャドウイング項を追加すれば、シャドウイングを計算するコストだけでライトシャフト/ゴッドレイを生み出せるだろうと考えた。

我々はこの方針に従うことを決めた。

ボリューメトリックフォグ#

このレイマーチングの解法と合わせたインスピレーションは我々が”ボリューメトリックフォグVolumetric Fog”と呼ぶ新しい解法の開発へと我々を導いた。

映像

#

映像

複数の光源で、一貫して、正しく、かつ、完全に機能している。

アルゴリズムの概要#

アルゴリズムの概要#

  • 中間ストレージとしてのボリューメトリックテクスチャ
  • 効率的にレイマーチおよび書き込みを行うためにコンピュートシェーダおよびUAVを使う

パスを効率的に分割し、個別にそれらを起動することを可能にするため、中間的かつ部分的な結果に対するストレージとしてボリューメトリックテクスチャを使った。

我々は効率的かつ非常に便利な方法でボリューメトリックデータを書き込むためにコンピュートシェーダと3DテクスチャUAVを用いた。

アルゴリズムの概要#

  • 典型的な散乱の工程を分割する
    • 関与媒質の密度推定
    • in-scatterされるライティングの計算
    • レイマーチング
    • エフェクトの適用

我々のアルゴリズムの鍵となるアイデアはレイマーチングアルゴリズムの典型的な工程を分離して並列化し、それらを個々に起動することである。

この方法で、我々は個々にアルゴリズムのすべての要素のスワップおよび調整の並列性や可能性を達成する。

アルゴリズムの概要#

密度推定←直列/並列に組み合わせられる/実行される→ライティング計算
3Dテクスチャ3Dテクスチャ
レイマーチング
3Dテクスチャ
フォーワード/ディファードで適用するシェーディングされたオブジェクト

我々は複数パスによるアルゴリズムの分割方法をこの図で確認できる。

  1. 最初で最も重要な部分はすべてのボリューメトリックセルに対してライティングおよびシャドウイング計算を行うことである。
  2. 並列(同じパス、または、並列パス)、または、直列に、関与物質の密度を推定しアニメーションした。
  3. ボリュームテクスチャに格納したこの情報を用いて、ボリュームを通して2Dレイマーチングを行い、ボリュームスライスに結果を格納した。
  4. そして、最後に、ピクセルシェーダを用いて、フォーワードまたはディファードシェーディングされるオブジェクトに対してスクリーン上で情報を適用した。

ボリュームテクスチャレイアウト#

我々のボリューメトリックフォグの中間ストレージはどのように見えるか?

まず、我々は最も単純なデータレイアウトを試した --- ワールド空間座標に並行な直方体cuboid。これは複数の利点をもたらした --- 例えば、非常に簡単なテンポラルフィルタリングは、そのようなボリュームを通したレイマーチングは複数のサンプルを必要としたのだが、低速でありエイリアシングアーティファクトを生み出した。

代わりに、我々はカメラ錐台に並行なレイアウトを用いることを決めた。我々は幅と高さに正規化済みデバイス座標normalized device coordinatesを用いる直方体に錐台を直接対応させ、深度スライスには、指数関数的な深度分布を用いる。

我々は様々な深度分布を試し、最終的にカメラ近くに集中したものとなった --- これは最も精度を必要とし、エイリアシングアーティファクトが簡単に現れる所である。

テクスチャを視錐台に並行とすることはテンポラルエイリアシングやフリッカリングが起こりがちになるというようないくつかの欠点を持つが、レイマーチングは深度スライスを通した単なる並列スキャンである。

我々はプラットフォームに依存する160x90x64か160x90x128の大きさのボリュームを用いた。これはほぼすべてのパスの固定コストをもたらし、スクリーン解像度に依存しない。

160x90x64レイアウトでは、テクセル数は720pのサーフェスにおけるテクセル数と等しい --- だが、すべてのセルに対して、一度だけライティング計算を行う。

エフェクトの範囲はアーティストが定義した設定に依存するが、50から128メートルの間の距離をあける --- 長い距離フォグを現世代のアートディレクションと矛盾しないように保つため --- しかし、より長距離のフォグを行うことができないであろう理由はない(指数関数的な深度分布かカスケードされたアプローチを用いて)。

#

このボリューメトリックテクスチャ解像度は十分か?

ボリューメトリック解像度 --- 低すぎる?#

  • 視線view ray全体に対して情報を格納する
  • かつ、それに沿ったすべての深度に対して --- tex3Dフィルタリング
  • すべての1080pピクセルは適した情報を得る
  • エッジアーティファクトなし!
  • 欠点 --- ソフトな結果

ボリュームテクスチャの解像度は極めて低いように見えるかもしれないが、これで十分である。

  1. レイに沿って格納されるすべての深度に対して低周波の情報を格納する。
  2. エフェクトを適用するとき、ボリューメトリックデータにquadrilinearフィルタリングを用いるという事から、ボリュームテクスチャの1つのテクセルを見ることは不可能である。
  3. すべての対象のピクセルはネイティブ解像度から適切で精細な深度に関する情報を受け取る。
  4. perspective correctionやボリューム形状は情報が正しく分布されることを確実にする。
  5. 深度の不連続性におけるエッジアーティファクトを得ない(次のスライドで説明される)。

明らかに、生み出されるエフェクトは非常にソフトであり、高周波のジオメトリ詳細を損なうが、これは我々のアートディレクションにフィットしており、現実にかなり似ている(現実の大気では、複数散乱エフェクトが起こり、ライトシャフトの見た目を十分にソフトにするため)。

シーン深度に頼らない最後の利点はシャドウが準備され次第通常のシーンレンダリングと並行してこのパスを計算する可能性である --- 例えば、コンソールAPIやMantleでのAMDハードウェア上の非同期コンピュートを用いて。

2Dアプローチ --- エッジアーティファクト#

通常の2D低解像度レンダリングを用いるとき、主な問題はエッジの不連続性に関する挙動である。低解像度のポストエフェクト計算に対して、我々は多くの取り得る深度フラグメントからある特定の深度を選び出さなければならない --- こうして、いくつかの最終的にシェーディングされるフラグメントは不適切な情報を持つだろう --- 近傍から補間または選択のいずれかが行われて(バイラテラルアップサンプリング)。

3Dテクスチャ --- 適切なエッジ#

幸いにも、3Dテクスチャと3D補間を用いると、そのような問題を抱えない。

すべてのフル解像度フラグメントとその深度は計算される関数の適切な区間線形補間を得る。

これは依然として低解像度であり、“ギザギザしているjagged”可能性がある一方で、エッジの不連続性アーティファクトを持たない。

エイリアシング問題#

ローパスフィルタリングが高周波源の情報のテンポラルエイリアシング/フリッカリング問題を取り除く方法をこの図で確認できる。

エイリアシング問題#

  • 4つのシャドウカスケード 1536x1536
    • 細かすぎる
    • ボリュームのナイキスト周波数以上のシャドウイング
    • 大量のエイリアシング、フリッカリング
    • ローパスフィルタを適用する必要がある
    • ナイーブな32タップのPCF = 許容できないパフォーマンス

我々のアルゴリズムの最初の工程はフォグが太陽の散乱のシャドウイングを計算するのに使われるシャドウマップを準備することである。

なぜ必要なのか?

通常のシャドウイングカスケードは非常に高解像度であり(4つのカスケード、プラットフォームに依存する1536x1536または1Kx1K)、それらの密な高解像度情報を持つ。

これは我々にはかなり細かすぎた。特に、近距離で、かつ、最初の2つのカスケードでは、最初の2メートルに凝縮した。

なめらかで近似的なボリューメトリックフォグでは、動く草木などによるフリッカリング/エイリアシングアーティファクトを減らすためにさらに低解像度のものを必要とした。広いカーネルのPCFを用いる最初の実装は非常に乏しいパフォーマンスや依然としていくつかのフリッカリングやエイリアシングアーティファクトを持った。

指数シャドウマップ#

  • テストのために深度を比較しない
  • シャドウイング確率を推定する
  • シャドウイングテストを計算するのに効率が良い
  • ダウンサンプリングさせることができる!
    • 256x256のR32Fカスケード

その解法はExponential Shadow Mapsアルゴリズムに由来する。

これは推定されるシャドウイング確率のフィルタリングを可能にする単純なアルゴリズムであり、それ故に、シャドウイング関数をダウンサンプリングする。

シャドウイングテストを計算するのは自明であり、非常に効率的である。ESMのいくつかの単純なコードスニペットがボーナススライドにある。

指数シャドウマップ#

  • フィルタできる(分離可能separableなブラー)
  • 欠点がひとつ --- シャドウのリーク
    • 関与媒質では無視できる
  • ボーナススライドにコードスニペットがあります!

まず、我々はカスケードシャドウマップを4回ダウンサンプリングする(R32Fの1024x256テクスチャを対象とする)。ダウンサンプリング中に、指数シャドウイング関数を計算する(Chebyshevの不等式ではなく指数関数を用いるVariance Shadow Mappingの拡張であるExponential Shadow Mappingを参照)。

我々はシャドウをより柔らかくし、エイリアシングアーティファクトを取り除くため、このパス中に(2つの別個の工程としての)追加の分離可能なボックスフィルタも行う。

通常のレンダリングでは実践的でなくするESMの欠点のひとつ --- シャドウリーク --- は関与媒質における我々の場合では目立たなかった。

スポットライトのアンチエイリアシング#

アルゴリズムの詳細#

シャドウのカスケードPS: シャドウマップのダウンサンプリング&ブラーESM
CS: 密度推定とボリュームライティング密度&in-scattering
CS: 散乱方程式を解く累積された散乱
深度バッファPS: フォグを適用最終色バッファ
色バッファ

故に、我々のアルゴリズムの第一段階はシャドウイング情報のダウンサンプリングである。

アルゴリズムの詳細#

ダウンサンプリングされたシャドウ情報が準備できたら、関与媒質のライティング計算を進めることができる。

密度推定とボリュームレンダリング#

  • 関与媒質の密度推定
    • 風によってアニメーションするプロシージャルなパーリンノイズ
    • 鉛直減衰vertical attenuation
    • 散乱係数はボリュームテクスチャのAチャネルに格納される
  • in-scatteringのライティング
    • メインライトに対するESMシャドウイング
    • 一定のアンビエント項
    • ポイントライト全体でループする
    • ボリュームテクスチャのRGBチャネルに格納される

我々はほんの少しだけ小さい帯域幅の使用率と同じ望ましい解像度のために密度とライティング計算を組み合わせたが、これらは分割でき、完全に分離できる。

密度計算はかなり素直であり、これは単なる風によってアニメーションするパーリンノイズの1オクターブである。我々は複数のオクターブを用いようとしたが、結局、差異は追加されるコストにしてはかなり微妙であった。

我々は、水蒸気の粒子のような通常で重たい粒子は指数分布で地表面ground levelの周りに集まる傾向にあるので、鉛直方向の媒質密度の減衰も計算した。

散乱係数はボリュームテクスチャのアルファチャネルに格納させた。

ライティングパートでは、我々は視錐台と交差していた、または、大気に影響を与えるライトとしてアーティストによって印を付けられた、メインライト(太陽/月明かり)、一定のアンビエント項、複数の動的ポイントライトからのライティングを単純に累積した。

我々は密度によって変調したライティング情報をボリュームテクスチャのRGBチャネルに格納した。

密度推定とボリュームレンダリング#

  • AC4におけるin-scatteringライティングの位相関数
    • 物理ベースではない(代わりに、アート駆動である) --- 2色(太陽方向、反対方向)

AC4では、物理ベースの位相関数を持たなかった。(太陽の方向を向いた)色のグラデーションのライティングは純粋にアート駆動であった。

我々は2つの位相関数の色を持っていた --- 太陽の方向と反対方向、完全に等方的な形状を持つことと別に。

明らかに、いずれかの位相関数はより物理的に正確なエフェクトを達成するためにこのパスで適用できる(後に説明する)。

アルゴリズムの詳細#

第三工程はフォグボリュームを通して線形にマーチングすることで散乱方程式を解き、数値積分numerical calculusの解法を行うことである。

散乱方程式を解く#

  • ボリュームの中をレイマーチする
  • 消散係数を累積する
  • アルファに格納される透過率を計算するためにBeer-Lambertの法則を適用する
  • RGBチャネルにあるin-scatteredされた光を累積する
  • 同様に透過率をin-scatteringに適用する

では、どうやってこの散乱方程式を解くか?

out-scatteringエフェクトは、与えられた距離に対する密度の積分の指数関数的なフォールオフ関数であるBeer-Lambertの法則で説明される。

in-scatteringに対して、今の所、in-scatteredされたライティングの単純な合計である(out-scatteringに基づく距離を計算に入れる)。

我々はボリュームテクスチャに計算され累積されたin-scatteringの値をすでに持っている。

故に、すべてのレイに対して、カメラを視点にボリュームの中を単純にマーチングし、密度の合計を計算し、in-scatteringする放射輝度とout-scatteringのフォールオフファクタを累積することができる。

散乱方程式を解く#

  • 2Dのコンピュートシェーダ
  • ブルートフォースな数値積分numerical integration
  • 深度スライスの中をマーチングして累積する
  • UAV書き込みを使う

我々のコンピュートシェーダはすべてのステップでin-sctteredされるライトとフォグ密度を累積する(数値計算的な解法)。

この方法では、我々は、カメラから与えられた3Dの点までのin-scatteredされる光の量、および、(out-scatteredされる入射光の量を説明する)累積される関与媒質の密度という情報をすべてのテクセルで持つボリューメトリックテクスチャとなる。

このデータは(オブジェクトを描画するときに直接適用する)フォワード法か(フルスクリーンクアッドパスのような)ディファード法のいずれかですぐに適用できる。

散乱方程式を解く#

この図では、2Dコンピュートシェーダのスレッドグループが、in-scatteredされるライティングと消散係数を累積しながら、3Dボリュームの中をマーチングする方法を確認できる。

なぜparallel sumではないのか?#

  • このアプローチをやってみた!
  • “Parallel Prefix Sum (Scan)”
  • …だが、ブルートフォースより20から30%遅かった!
    • LDSバンクが衝突する
    • シェーダ占有率がより悪い
    • Cache thrashing / 不十分な局所性?
  • 依然として、いくつかのケースでは2D用のほうが良いかもしれない

エフェクトを適用する#

不透明および透明オブジェクトの複数のレイヤとバイリニア3Dテクスチャフィルタリング

この図では全体のビューのレイ情報を格納するためにソリッド(1)と複数の透明オブジェクト(2)と(3)の両方に関してボリューメトリックフォグ情報を適用できる方法を確認できる。これらすべては適切でフィルタされた透過率とin-scattering情報を持つ。

エフェクトを適用する#

  • ピクセルのボリュームテクスチャの位置を計算する
  • 単純な3Dテクスチャルックアップ
  • フォワードやディファードで行うのは自明である
  • …任意数の透明レイヤと互換性がある
// 値を読み出す
float4 scatteringInformation = tex3D(VolumetricFogSampler, positionInVolume);
float3 inScattering = scatteringInformation.rgb;
float transmittance = scatteringInformation.a;

// litピクセルに適用する
float3 finalPixelColor = pixelColorWithoutFog * transmittance.xxx + inScattering;

スクリーン上でのエフェクトの最終適用はディファードおよびフォワードの両方でじめいである --- 特殊なトリックはなく、積和演算で結合された、単なる3Dテクスチャからの簡単なバイリニアルックアップである。

注目すべきはThing worth noting is that、エフェクトが任意の数の透明オブジェクトレイヤと互換性があることである。

#

Xbox Oneでのパフォーマンス#

トータルコスト1.1ms
シャドウマップのダウンサンプリング0.163ms
シャドウマップのブラー0.177ms
ボリュームのライティングと散乱の計算0.43ms
散乱方程式を解く0.116ms
スクリーン上での適用(組み合わせられる)0.247ms

トータルコストは驚くほど小さく、約1.1msであった。倍の解像度で計算すると1.6msのコストであった。

最もコストの高い部分は密度の構築とボリュームのライティングであり、約.043msであった。

残りのパスは、ライティングと組み合わせられ、“タダ”になるであろう”適用”パスを除いて、すべて0.2ms以下であった。

最適化#

  • レジスタ数を少なく保つためにパスを分割する
  • 低解像度のESMは超効率的!
  • パーティクルや半透明オブジェクトに対してESMシャドウマップを再利用する
  • パーティクルのライティングやシャドウイングに対してボリューメトリックフォグのライティングボリュームを使う
  • ディファードライティングとフォグの適用を組み合わせる

まず、ボリューメトリックフォグは高いwave占有率と低いVGPR数から最も利益を得るエフェクトのひとつであった --- 様々なパスに分割することは有用である。

ボリューメトリックフォグのコストの幾らかは実際にはシャドウマップのセットアップのコストである --- パーティクル、半透明や透明オブジェクト(大海など)のような他の低周波ライティングに対してこれを再利用することは大いに理に適っている。

また、テクスチャでのライティングの計算や複数ライト全体のループのコストはそのようなレンダパスで再利用できるだろう --- 単純なボリューメトリックテクスチャルックアップによって。

最後に、非常に大きなフォグ距離を持つ完全なライティングを計算する必要はない --- ある距離以降では、シャドウイングとライティングはLODできるだろう。

最適化の続き#

  • Gバッファのレンダリング中に非同期コンピュートを用いてフォグを処理する

または

  • タイルの最大Z値を持つならば、カリングにそれを使う(ライティング/レイマーチングでの早期脱出early out)
  • クラスタ化/タイル化clustered/tiledしたローカルライトを使う

いくつかの他の最適化はいずれかの実際のレンダリングされるジオメトリの背後にあるボリューメトリックテクスチャの一部でいくつかの早期脱出を行うことを含む。エンジンがある形式の利用可能な階層的Zバッファを持つ場合、そのような値はボリューメトリックフォグによって読み出され、早期脱出のために使われることができる。

同様に、すべての可視ライト全体をループするひつようはない --- Forward+やClustered Shadingのような解法はフォグライトカリングで使える。

そのような情報がエンジンで使えなかったり、見積もられるprojectedパフォーマンス上の利益が十分に大きくないであろう(例えば、屋外の長距離シーンが多くある)場合には、ボリューメトリックフォグ計算に対して次世代コンソールの非同期コンピュート能力を使えるだろう。カリングのないアルゴリズムはシーンのジオメトリに依存しないので、シャドウマップが準備でき次第計算できる。ボリューメトリックフォグは帯域およびALUの両方に関して極めて重くなり得る。そのため、Gバッファ埋めのような頂点ヘビーなパスと並列に行うことは理に適っている。

ディファードライクなライトの注入#

似た方法で、ライティングもフォワードベースのライティング技術の代替としてボリュームに注入できるだろう。

それは、ライトのボリューム境界ボックスを計算し、それと交差するセルでのみライティングを処理できるだろう。これは非常に簡単であり、DX11/次世代コンソールの間接ディスパッチ機能を用いて行うことができるだろう。

この最適化は計算に多くのVGPRを使う、つまり、エリアライトのような非常に複雑なライトに対して有用となり得るだろう。

AC4の先へ#

最後のプレゼンテーションのセクションでは、AC4の後に開発したボリューメトリックフォグへの拡張機能を説明したい。

  1. エフェクトをさらに物理ベースにする方法 --- 解析的光源やSHベースの光源に対する物理ベースの位相関数のサポートのような欠けたピース
  2. テンポラルリプロジェクションとジッタリングを導入することによってエフェクトをさらに安定にする

アンビエント/GIのサポート#

フォグのアンビエント/空ライティングのサポートが足りないと、影付けされる範囲でシーンが暗くなりすぎてしまう。

いくつかの光はout-scatteredされるが、ライティング不足のためにin-scatterdされる光が一切なく、現実感のない結果を生み出す。故に、幾らかのGIを追加する必要がある。

アンビエント/GIのサポート#

この比較では、追加した空ライティングが結果を改善し、影付けされる範囲に適切なフォグを追加するかを確認できる。

誇張されたexaggeratedGI#

最後に、この(フォグとGIを誇張した)スクリーンショットでは、GIの色が最終的なフォグ色に寄与し、適切な色の空間的な変化を追加することを確認できる。

アンビエント/GIのサポート#

  • Henyey-Greensteinの位相関数に対してZonal SHを計算する
    • ビュー方向によってそれを回転する
    • 2次のSHで同等
    • float4(1.0f, dir.y, dir.z, dir.x) * float4(1.0f, g, g, g);
  • 与えられた点と位相関数でアンビエントライティングのSHの乗法的積分product integralを計算する
    • …色チャネルあたりひとつのドット積!

アンビエントライティングやGIに対する非常に一般的なライティングストレージ基底のひとつは球面調和関数である。

これらはこれらをとても有用にする複数の数学的特性(正規直交性、回転不変性、など)を持つが、もうひとつはZonal球面調和関数の使用の容易さである。

これらは(特に低次のSHに対して)自明に回転でき、同様にボリューメトリックフォグに対して有用である。

HGの位相関数はZonal SHへの自明な拡張を持ち、2次のそれに対して、容易に回転させることができる(コードはスライドにある)。

そして、ボリューメトリックフォグの応答を計算するには、ビューベクトルによって回転した位相関数のSH展開と格納された空ライティング/GIのSH表現とのSH乗法的積分を計算するだけで良い。

テンポラルリプロジェクション#

  • アンダーサンプリングとエイリアシングが依然として発生するかもしれない
  • テンポラルジッタリングおよびリプロジェクションを使う
  • 一般的なモダンなAA技術
    • (Crysis 2/3、Killzone: Shadowfall、Assassin’s Creed 4、Unreal Engine 4、Infamous: Second Son、などなど!)
  • 2Dの場合よりさらに簡単!

ダウンサンプリングされたSM表現を用いることによってボリューメトリックフォグに関するエイリアシングおよびアンダーサンプリング問題を取り除くためにかなりの時間を費やす一方で、依然として幾らかのアンダーサンプリングアーティファクトが存在するかもしれない。

それを直すためのアイデアのひとつは毎フレームサンプルパターンをジッタリングし、複数のフレームからそのようなパターンを組み合わせるためのテンポラル平滑化とリプロジェクションを用いることによってテンポラルスーパーサンプリングを用いることである。

これはますます多くのゲームにおいて一般的なAA技術として使われるが、同様にボリューメトリックフォグに対して使うことができる --- リプロジェクションは2Dの場合より3Dのほうがさらに簡単である。

2Dにおける再投影での問題#

再投影は、シーン上のオブジェクトが動くときにocclusion/disocclusionの問題があるので、2Dにおいて通常では問題となる。(特にジッタリング時の)そのような動きを検出し、結果の穴を埋めるための適切なデータを見つけることの両方は難しい。

故に、通常、アルゴリズムは起こり得るshakingと動的なオブジェクトのblurring/tracing/ghostingとの間のスイートスポットを見つけるようと奮闘する。

ボリューメトリックリプロジェクション#

3Dではより簡単である。移動後に動的オブジェクトによって占められる空間は依然として無効である一方で、その背後にあるデータのすべては適切である(いずれかの早期カリング最適化を用いない場合)。錐台と並行なボリュームの外側であったデータのみ無効である。(ただし、未だに、明らかな再投影問題は強力に視点依存で異方的な位相関数で起こり得る。)

サンプルのジッタリング#

  • ノイズとエイリアシングをトレードする
  • ノイズはフィルタし易い
  • テンポラル領域でジッタリングおよびフィルタリングできる!

もうひとつのエイリアシングに対抗する技術は空間的なグリッドでのサンプルのジッタリングである。通常のグリッドサンプリングは対処しづらいエイリアシングを生み出す(ソース信号で見えない低周波要素が現れるので)一方で、ジッタリングされたグリッドサンプリングは高周波ノイズとエイリアシングをトレードする。

ノイズや高周波信号は低解像度カーネルを用いて容易にフィルタリングおよびブラーすることができる。

さらに、時間的および空間的領域の両方においてジッタリングおよびフィルタリングが可能である。

サブセルのジッタリング/スーパーサンプリング#

この2つのスクリーンショットは、どれだけより良い結果が最も単純な1サンプルのテンポラルジッタリングおよびリプロジェクションのみによって達成されるかを示す --- ほぼすべてのエッジアーティファクトはなくなった!

我々はいずれの複雑な3Dのジッタリングされたグリッドサンプリングパターンも確認しなかったが、結果がさらに良くなる可能性があるので、今後に調査する価値がある。

スペシャルサンクス#

ご質問は?#

参考文献#

ボリューメトリックフォグで使うExponential Shadow Maps#

  1. シャドウマップのダウンサンプリング/指数空間への変換
float4 accum = 0.0f;
accum += exp(ImputTextureShadowmap.GatherRed(pointSampler, samplingPos, int2(0, 0)) * EXPONENT);
accum += exp(ImputTextureShadowmap.GatherRed(pointSampler, samplingPos, int2(2, 0)) * EXPONENT);
accum += exp(ImputTextureShadowmap.GatherRed(pointSampler, samplingPos, int2(0, 2)) * EXPONENT);
accum += exp(ImputTextureShadowmap.GatherRed(pointSampler, samplingPos, int2(2, 2)) * EXPONENT);
  1. 分離可能な11ピクセル幅のボックスフィルタ(2つの自明なパス)
  2. シャドウマップを適用
float receiver = exp(shadedPointShadowSpacePosition.z * EXPONENT);
float occluder = InputESM.SampleLevel(BilinearSampler, shadedPointShadowSpacePosition.xy, 0);
shadow = saturate(occluder / receiver);

散乱方程式を解く#

void RayMarchThroughVolume(uint3 dispatchThreadID) {
    float4 currentSliceValue = InputTexture[uint3(dispatchThreadID.xy, 0)].rgba;
    WriteOutput(uint3(dispatchThreadID.xy, 0), currentSliceValue);

    for (uint z = 1; z < VOLUME_DEPTH; ++z) {
        float4 nextValue = InputTexture[uint3(dispatchThreadID.xy, z)].rgba;
        currentSliceValue = AccumulateScattering(currintSliceValue, nextValue);
        WriteOutput(uint3(dispatchThraedID.xy, z), currentSliceValue);
    }
}

ブルートフォースなレイマーチング

散乱方程式を解く#

Beer-Lambertの法則から方程式を適用する

// 光散乱方程式への数値計算的な解法の1ステップ
float AccumulateScattering(float4 colorAndDensityFront, float4 colorAndDensityBack) {
    // rgb = これまでの累積されたin-scatteredされた光、a = 累積された散乱係数
    float3 light = colorAndDensityFront.rgb + saturate(exp(-colorAndDensityFront.a)) * colorAndDensityBack.rgb;
    return float4(light.rgb, colorAndDensityFront.a + colorAndDensityBack.a);
}

散乱方程式への反復的な数値計算的解法の1ステップ

// 最終的な散乱の値の書き出し
void WriteOutput(in uint3 pos, in float4 colorAndDensity) {
    // 最終値 rgb = これまでの累積されたin-scatteredされた光、a = out-scatteringで発生したシーンの光の消散
    float4 finalValue = float4(colorAndDensity.rgb, exp(-colorAndDensity.a));
    OutputTexture《pos》.rgba = finalValue;
}

最終的な散乱の値の書き出し

制御可能な密度#

  • 密度はアーティストが制作できる
  • レベルでの密度マップ
    • 例: 沼地、ホコリまみれの建物
  • パーティクル注入
    • 煙の雲
  • ボリューメトリック形状の注入
  • …CGI/映画ではすでに行われる
    • Wrenninge et al., SIGGRAPH 2010を参照

我々の場合では、密度は単純なアニメーションするパーリンノイズの関数であった一方で、いずれかの方法ではアーティストによって制御できるだろう。

密度は、一部の非常に霞がかったオブジェクトや沼地(霧)やホコリまみれの建物のような散乱する粒子に対するレベルで制作したり、描いたりすることができるだろう。

これはパーティクルシステムかいくつかの解析的ボリューム形状/力場によって動的にボリュームへ注入できるだろう。

映画/CGI業界でとうの昔に行われた方法を確認するにはSIGGRAPH2010でのWrenninge et al.を参照のこと☺