今日は実装用のメモをとっておこうと思います。
自分さえわかればいいので,詳しい説明は省略します。
1. [Bitterli 2020]
[Bitterli 2020]では,アルゴリズム5にSpatiotemporal reuseを使用したRISアルゴリズムが載っています。
まずは画面サイズ分のピクセルを格納するための配列を用意して,これをリザーバーとして使用します。
あとは,アルゴリズム5にあるように
- 初期候補の生成(Generate initial candidates)
- 初期候補に対する可視性を評価(Evaluate visibility for initial candidates)
- 時間的再利用(Temporal reuse)
- 空間的再利用(Spatial reuse)
- ピクセルカラーを計算(Compute pixel color)
の順で処理していきます。
まず,初期候補の生成ですが,アルゴリズム3に従ってリザーバーに格納していきます。
アルゴリズム3に登場する\(r.y\)や\(r.{\rm w}_{\rm sum}\)などはリザーバーのメンバー変数を意味します。その定義はアルゴリズム2に記載されています。
アルゴリズム5に戻って,次の処理は初期候補の可視性の評価についてです。これはサンプル\(y\)を使ってシャドウレイをトレースすれば求まると思います。サンプルの定義は[Bitterli 2020]では言及されていませんが,[Ouyang 2021]では次のように示されているので,これを参考に実装すればよさそうです。
pickTemporalNeighbor()についてはセクション5に記載があり,現在のピクセルの周囲30pixelの半径で,低ディスクレパンシー数列から5個のランダムな点をサンプリングしているとあります。HaltonやらHammersleyやら,そういった類の数列を使ってサンプリングする実装にすればよさそうです。
combineReservoirs()についてはアルゴリズム4に記載があります。
バイアスドなアルゴリズムでは,形状やマテリアルが大きく異なる隣接ピクセルを再利用するとバイアスが大きくなるため,カメラ距離と現在ピクセルと隣接ピクセルの法線の間の角度を比較して,閾値を超えたら棄却するということをやっているそうです。
アルゴリズム5の続いての処理は,Spatial reuseです。
pickSpatilaNeighbors()も,低ディスクレパンシー数列を使ってランダムな点をサンプリングしておけば良さそうです。
combineReserrvoirs()は先ほど説明したので,同じ処理を実行すればよいです。
アルゴリズム5の最後の処理は,ピクセルカラーの計算です。
これは被積分関数にリザーバーのサンプル点を渡して,式(6)を使ってRISの重みを求めて乗算すれば良いようです。
アルゴリズム3に具体的な式が載っています。
あと、細かい所としては Generate initial candidates, Evaluate visibility for initial candidates, Temporal reuseのループ数が同じなので,1つのシェーダにまとめてしまってもよさそうです。
Spatial reuseはシェーダ内でループすると,処理時間の関係でGPUハング(TDRに引っかかる)する恐れもあるので,CPUでループした方が実装上は安全かもしれません。
2. [Ouyang 2021]
[Bitterli 2020]では,直接照明に対して適用するものでした。間接照明に対してもReSTIRを適用しようとするのが,[Ouyang 2021]です。
ReSTIRがグローバルなライト空間に初期サンプルを配置するのに対して,ReSTIR GIはシェーディング点周辺の方向のローカルな球の空間上に初期サンプルを配置します。レイの原点に向かって散乱する光の量でRISの重みを決定します。空間的,時間的な両方でこれらの点をリサンプリングすることで,シーンにおける間接照明を近似する分布からの重みづけサンプルを生成することができ,大幅な誤差低減につなげます。
オリジナルのReSTIRとReSTIR GIの違いですが,図2に示されています。オリジナルが(a)と(b)で,ReSTIR GIが(c)と(d)になります。
ReSTIR GIでは,Visible pointと呼ばれる可視点からランダムな方向にレイを飛ばし,ヒットしたところを初期サンプルとします。空間的リサンプリングと時間的なリサンプリングは同様の方法で適用されます。(c)と(d)を見ると分かりますが,オリジナルでは寄与を与えるのはライトにヒットするものだけですが,ReSTIR GIでは,2-Bounceするサンプルも寄与として取れる可能性があるため,意味がある間接照明を与える方向を見つけることが可能になります。
[Bitterli 2020]では,リザーバーを更新するUPDATE()のみが定義されていましたが,アルゴリズム1に示すように,別のリザーバーをマージする関数が追加されています。
● Initial Sampling
visible pointからランダムな方向にレイをトレースします。そして,最も近い交差点をスクリーン空間の初期サンプルバッファに記録します。交差点における位置座標,法線,放射輝度,Next Event Estimation(NEE)で使用する乱数,また同様にピクセルの位置座標と法線も記録します(Sample構造体を参照)。
● Temporal reuse
初期サンプルバッファからのサンプルを使用して,Temporal Reservoir Bufferを更新します。現在フレームで作成されたものと
,既存のバッファの間でランダムに選択することによって更新します。
● Spatial reuse
Spatial Reservoirを更新するために近接ピクセルからランダムにtemporal reservoirを選択します。バイアスを消すために,現在ピクセルの深度と法線を比較することによって類似する幾何的特徴を持つ近接ピクセルを選択します。
まず最初の初期サンプルですが,アルゴリズム2に示されています。
次に,Temporal reuseですが,アルゴリズム3に従って実装します。
\(p_q(\omega_i)\) ⇒ 各ピクセル\(q\)における可視点\(x_V\)に対応するBSDFの確率密度関数
\({\hat p}_q(\omega_i)\) ⇒ 各ピクセル\(q\)における\(L_o(x_s, -\omega_i)\) (式(10))
添え字のqが付いていないものは,そのサンプル位置におけるsourcePDFとtargetPDFを計算をすればよいかと思います。
UPDATE()関数はアルゴリズム1に示されているので,問題ないでしょう。これでTemporal Reservoir Bufferから取得したリザーバー\(R\)が更新できたので,Temporal Reservoir Bufferに格納して値更新します。
最後に,Spatial reuseのステップですが,アルゴリズム4に従って実装します。
アルゴリズム内に出てくる幾何類似度のチェックですが,サーフェイス法線が\(25^{\circ}\)以内,正規化された深度の差分が\(0.05\)以内であれば類似と判定する[Bitterli 2020]と同じ方法をとっているそうなので,これを参考に実装すれば良さそうです。
Calculate \(|J_{q_n \rightarrow q}|\)は式(11)を使って計算するだけで,位置座標と法線ベクトルがあれば計算することが出来ます(図6参照)。
アルゴリズム4ではわかりやすいように,17行目から19行目のfor文を分けてくれていますが,Qのメモリ領域を取るのがシェーダ実装上でめんどくさそうな気もするので,15行目あたりに18・19行目の処理を移動して,16行目の初期化を3行目あたりにもってきて,なるべく変数確保をせずに,効率的に実装した方がよさそうな感じです。
基本的なReSTIR GIの実装は以上ですが,[Ouyang 2021]ではSample構造体が大きくなりやすいので,サーフェイス法線を4byteに圧縮,放射輝度にはhalfを使うなどして,48byteにしてメモリ帯域を減らすなどの工夫をしているそうです。
また,すべてのピクセルで長い経路をサンプリングすると,パフォーマンスに大きな影響を与える可能性があるため,25%のピクセルにおいてのみマルチバウンスパスを追跡しているそうです。実装的には画面を\(64 \times 32\)ピクセルのタイルに分割して,タイル単位でロシアンルーレットを適用し,ロシアンルーレットで不合格になったものはシングルバウンスパスを使用して描画し,サンプル点における直接照明を計算します。ロシアンルーレットで合格になったものは,マルチバウンスパスになりますが,ロシアンルーレットの確率を使用して重みづけするそうです。
…というわけで,めちゃくちゃざっくりですが,実装のメモでした。
あと分からないところは,論文のサンプルコードなどを頼りに実装していけばよいかと思います。
参考文献
- [Bitterli 2020] Benedikt Bitterli, Chris Wyman, Matt Pharr, Peter Shirley, Aaron Lefohon, Wojciech Jarosz, “Spatiotemporal reservoir resampling for real-time ray tracing with dynamic direct lighting”, ACM Transactions on Graphics, Vol.39, No.4, 2020.
- [Ouyang 2021] Y.Ouyang, S.Liu, M.Kettunen, M.Pharr, J.Pataleoni, “ReSTIR GI: Path Resampling for Real-Time Path Tracing”, High-Performance Graphics 2021.