新年明けましておめでとうございます。
本年もProject ASURAをよろしくお願い致します。
昨年から、ちょっと分け合って各社さんとお話しする機会があって,その中でシャドウについて困っているという話題になりまして。
改めて、シャドウ関連を調べなおしているのですが,13年前にわからなかったことが,GPTさんのおかげでようやく分かるようになってきたので、
今日は今後の実装用にメモを残しておこうと思います。
資料は、下記になります。Real-Time Shadowsのページからダウンロードできます。
[Kasyan 2013] Nikolas Kasyan, “Playing with Real-Time Shadows”, SIGGRAPH 2013.
まずは、コンタクトシャドウについてから。

ベント法線を用いて適用します。ベント法線というの遮蔽されていない方向の平均を表します。

コアとなるアイデアはSSDOと同じです。
・スクリーン空間でオクルージョンを計算し,ライティングに乗算します。
・ソフトなコンタクトシャドウを生み出せる
・シャドウバイアスの問題も隠すことが可能。
・SAOのみに比べて大幅な品質向上

オクルージョン情報の生成ですが
・SSAOパス内で,ベント法線N’を計算し保存する
・ベント法線は遮蔽されない方向の平均
・任意のセルフオクルージョンを持たないクリーンなSSAOと,比較的に広範囲な半径を必要とする。
なので,SSAOをちろっと変更すればいいです。最近ですと,IntelのGTAOのサンプルだとベント法線計算してくれたりするサンプルがあるので,そういうのを参考にすればいいでしょう。
各ライトに対してですが
・dot(N, L)を通常のように計算
・dot(N’, L)を計算
・中心深度はフル解像度で,その他のタップはすべて,FP16の半解像度深度で計算
・2つの内積間の差分をクランプしたオクルージョン値で乗算することでライティングを減衰させる
…という計算をするそうです。
ベント法線を用いることで,バイナリパッキリ状態を防ぐというのがミソっぽいですね。
疑似コードで書くと次のような感じでしょうか?
auto dp0 = dot(N, L); auto dp1 = dot(N_bent, L); auto occlusion = saturate(dp0 - dp1); auto result = LightingResult * occlusion;

単純なトリック/近似
・スクリーン空間のライトベクトルに沿ったレイキャスティング
・カットシーンでは、影響を受ける深度バッファ範囲を指定します。
・レイの長さのトラッキングにより、適切なソフトシャドウの計算も可能
と書いてありますが,衝突点までの長さを求めておくことで,ソフトシャドウ計算に利用するようです。例えば棒が1本突っ立っているシーンを想像すると,地面に近い個所はハードシャドウ気味になりますが,棒の先端に対応する地面から離れている部分のシャドウはソフトシャドウ気味になるはずです。これをレイの長さを使って実現するというようです。詳しい計算方法が載っていないので、おそらくアドホックな実装なのではないかと思われます。
続いてカスケードシャドウマップの話題です。

カスケードシャドウマップの分割の際に考慮するべきこと
・カスケードされた分割錐台のオーバラッピング
・ニア平面に近い分割では、正確な対数分布を使用することは困難。
・最も近い分割を手動で調整
・効率的なカスケード分割は、カメラの近接平面と視野に非常に敏感。
・より大きなFOVはシャドウ錐台のオーバーラッピングを増加させる
・FOVを大きくすると、シーンの非表示部分でシャドウマップの無駄が増えます。
・ニア平面に近いほどシャドウの視錐台のオーバーラップが増加
・深度範囲が制限されたカットシーンのCSM境界を狭くする

ライト空間 vs. ビュー空間錐台のアライメント
・ビュー空間整列
・より良いシャドウ空間の利用
・錐台のオーバーラッピングが少ない
・高いシャドウマップサンプリング密度
・シャドウマップがアンダーサンプリングされる場合においてシャドウが安定しない(シャドウエイアシング – カメラ移動に対する shimmering )※shimmeringというは揺らぎやチラつき。

ライト空間整列されたシャドウの視錐台
・視錐台のオーバーラップの増加によるシャドウマップの使用効率の低下
・シャドウ・カスケード・キャッシュの効率化
・シャドウマップテクセルサイズのスナップを使用できる
・移動カメラによるアンダーサンプルシャドウマップに対してシャドウが安定する
wp-image-13868″ />
影響する要因:
・低いシャドウマップサンプリング密度
・深度バッファの精度
・カメラに相対する光源の向き

エエイリアシングを克服するためのさまざまなシナリオ
・サンシャドウ:スロープスケール深度バイアスでフロントフェイスで描画
・ポイントシャドウ:バックフェースでレンダリング,インドアについてうまく動作する
・離れたLODの分散シャドウ-両方の面をシャドウマップにレンダリング
深度バッファ精度の問題を克服するために遅延シャドウパス中の定数深度バイアスを使用する

・最近のゲームでは、ほとんどアンダーサンプルのシャドウが使用されています。
・カスケード分割は効率的ではない
・シャドウマップテクセルスナップ、オブジェクト単位のシャドウなどのトリック
・レベル/カットシーンごとに微調整されたソリューション
(今見ると,13年経ちますが問題はあまり解決されていないですね…。)

主な目標–達成しようとしていること
・カスケードシャドウマップの視錐台のオーバーラップの除去/最小化
・シャドウマップの未使用領域を除去/最小化する
・シーンの非表示部分でのシャドウマップの無駄を最小限に抑える
・シャドウマップのサンプリング密度を非常に高くする ー シャドウマップのテクセルスナップなどのテクニックが不要にする
・シーンのすべての領域で、ほぼ一定のシャドウマップサンプリング密度を保証する
・シャドウマップの密度を一定に近づけると、シャドウエイリアシングの問題に対処できる

カスケードシャドウマップに対する斜投影
・平行投影法の一種
・平行光線を交差させてイメージを投影します。(「プロジェクタ」) を、ターゲット投影平面を持つ3次元ソースオブジェクトから作成します。
・プロジェクターが投影平面に対して垂直ではない

プロジェクタは、2つの角度αおよびλによって定義される。
αは直線 (x, y, xp, yp) と投影平面との間の角度
λは、直線(x、y、xp、yp)と投影平面上のX軸との間の角度
L=線分の長さ (x, y, xp, yp) で,L1=L/z

・斜投影を使用する
・視錘台クリップ平面をシャドウマップ投影平面として使用する
・投影平面は5つの錐台平面から選択される(ファー平面は無関係)
・シャドウ投影の斜投影平面は、ライトの方向に基づいて選択される。
・平面法線とライト方向の間の内積の符号が最も近い平面と同じである平面を選択します。

・投影平面はセグメントに分割され、対数分布の近似値が得られます。
・平面セグメントは基本的にシャドウマップのカスケードです。
・遠くのセグメントは、同じシャドウマップ解像度でより多くの領域をカバーします。
・シャドーキャスタのCPUカリングは、斜錐台のセットで実行されます。

シャドウマップパラメータ化
・ 錐台セグメントを四角形に延長し、矩形シャドウマップを使用する
・対数分割の近似値を得るには、より多くの平面セグメントが必要です。
・無駄なシャドウ空間
・ビューカメラの透視ワープを斜投影と一緒に使用する
・ニア平面をシフトおよび拡大した仮想ビューカメラ
・無駄なシャドウスペースがほとんどない
・shimmeringを克服するのに十分なシャドウマップサンプリング密度がある場合に使用できる
・投影平面セグメントに対する対数分布

斜シャドウ投影
・シャドウマップは視錐台を正確にカバーします。
・シーンの非表示領域では、シャドウマップのごく一部のみが無駄になります。
・カスケードの重複なし
・キャスターが最も適切な平面セグメントに投影されるため、シャドウを受ける可能性のある領域では、シャドウサンプリング密度が保証されます。
・このアプローチは、ライトの方向に関係なく、ほぼ一定のシャドウマップサンプリング密度を維持するように設計されています。
・シャドウエイリアシングの問題の解決に役立ちます。

実装詳細
・シャドウマップ描画
・視錐台平面の各分割は個別に処理されます。
・ジオメトリシェーダは、必要に応じて平面上の複数のセグメント間で三角形を複製します。
・ビュー空間のZ座標に基づいて適切な平面のセグメントが選択されます。

・ディファードシャドウレンダリング
・結果として、すべての斜投影シャドウマップからシャドウを適用します。
・斜錐台が重ならないため、カスケード間の複雑なステンシルは必要ありません。
・グローバルシャドウマップセグメント/カスケードをインデックス化するテクスチャ配列
・フォワードシャドウレンダリング
・シャドウマップ領域へのシャドウ領域の1対1対応による単純なシャドウマップインデックス
・クラスターフォワードとクラスターディファードシェーディング
・シャドウの視錐台のオーバーラップなし
・クラスターを斜め投影のシャドウマップ領域に1対1で対応させた単純なシャドウマップ索引付け

斜シャドウ投影機能
・テクスチャ空間の効率的な使用
・シャドウエイリアシングの問題の改善
・保証されたシャドウマップサンプリング密度に近づけることができます。
・高解像度シャドウマップを使用する場合はエイリアシングがない(1~2K、最適な4K)
…というわけで、斜投影を使ったシャドウマップがかなりよさげな感じします。これとSDSM組み合わせれば最強じゃね?感が個人的にはあるんですが,どうなんでしょ。
昔からググり続けているんですが,まともな実装をみたことがないので,今年どこかで実装出来ればなぁーと思っています。
あるいは実装したよ!とか,ここに実装あるで、みたいな情報お持ちの方がいれば是非教えてください。よろしくお願い致します。