超雑訳 Stochastic Screen-Space Reflections

こんこよー。Pocolです。
今更感がめちゃくちゃありますが,分けあって
[Stachowiak 2015] Tomasz Stachowiak, Yasin Uludag, “Stochastic Screen-Space Reflections”, SIGGRAPH 2015: Advances in Real-Time Rendering course.
を見ることにします。
いつもながら、誤字・誤訳があるかと思いますので,ご指摘頂ける際は正しい翻訳例と共に指摘して頂けると有難いです。
特に断りが無い限り,画像は[Stachowiak 2015]よりの引用となります。







こちらは『ミラーズエッジ カタリスト』のコンセプトアートです。ご覧の通り、ほとんどすべてが反射的です。サーフェイスは一般的に滑らかですが、すべてが鏡のような反射ではないことは注目に値します。左の引き伸ばされた反射と、右の壁のぼやけた反射に注目してください。



フロストバイトにおけある会議室の写真のひとつですr。興味深いことに、この写真を見ると、それ自体が反射しているようには見えません。これは、軽視されがちなSSRの重要な特徴を浮き彫りにしています。これは、局所的な反射と遠方からの反射に対してスペキュラーオクルージョンを提供します。さらに、このシーンでは、ラフな反射がたくさんあり、特に床の反射率の変化もあります。また、例えば椅子の脚のように、反射するサーフェイスの接点に近づくにつれて反射が鋭くなっていることにも注目してください。



この写真は、レースゲームでよく見るようなものを表現しています。しかし、我々がサポートしたいいくつかの重要な特徴も強調されています。反射は垂直に伸びています。また、サーフェイスのラフネスと法線には高い周波数で変化があります。



そこで、我々がSSRに求める条件をまとめてみましょう。まず、シャープでぼやけた反射をサポートすること。

しかし、これは現実的なぼやけた反射ではありません…。


…我々は、反射サーフェイスが接触に近づくにつれてシャープになることを望みます。


また、垂直方向にも伸びるはずです。マイクロファセットBRDFを使用している場合、解析的なライトはすでにこれを行います。SSRもこの物理的な現象を示すべきです。


最後に、ピクセルごとの法線とラフネスの変化をサポートしたいです。



いくつかのSSRのテクニックを見て、それらが我々がここで求めている要件を満たしているかどうか、またどのように満たしているかを見てみましょう。これまで紹介したすべてのテクニックに目を通す時間はないので、我々の研究のきっかけとなったテクニックを中心に見ていくことにします。



まずは基本的なSSRアルゴリズムについて簡単に復習しておきましょう。可能な実装の詳細についてはいくつかのパブリケーションがあるので、あまり詳しくは触れません。基本的なことをもっと知りたい場合は、例えばMorgan McGuireとMichael Maraの論文[McGuire14]を参照してください。

とにかく、基本的なアルゴリズムは鏡のような反射でしか機能しないので、レイの生成は些細なことです。Gバッファの深度と法線を取得し、ミラー方向を計算するだけです。次に、同じ深度バッファを任意のアルゴリズムでレイ・マーチします。たとえば、スクリーン空間で一定の大きさのステップを踏む。サーフェスと交差するとき、交差点の色をフェッチする必要があります。ここにはいくつかのオプションがありますが、最も一般的なものは、前のフレームの最終ライティングを再投影し、それを返すことです。



Killzone Shadow Fallは、グロッシーナSSRのために、Image Space Gatheringに似た興味深いアプローチをしていました。それらはまず、画面上のすべてのピクセルに対して……シャープな反射画像を生成します。

画面上のすべてのピクセルに対して。

そして、このシャープな反射のブラーピラミッドを作成し、サーフェイスのラフネスに基づいてぼかし具合を選択します。これによって不連続性がないことが保証されますが、他のアーティファクトが発生する可能性もあります。ひとつは、どの程度のレベルのぼかし具合がラフネスの値に対応すべきかが明確でないことです。



そして法線の問題もあります。つまり、ブラーが特徴に対応していないため、ラフなサーフェイスでは基本的に消えてしまいます。



さらに、接触によるハードさがないため、ぼやけ具合は物体の近さではなく、ラフネスに由来するだけです。



すべての要件を満たすアプローチは、フィルタリングの有無にかかわらず、重点サンプリングすることです。このアプローチでは、シャープな反射をぼかす代わりに、方向を確率的にサンプリングすることでぼやけた反射を生成します。ラフなサーフェイスの場合、方向はより分散され、滑らかなサーフェイスの場合、方向は狭いビームになります。フィルタリングされたバリアントは、サンプリングにあらかじめぼかされたカラーバッファを使用します。

この方法の唯一の問題は、たくさんのレイを使わない限り、非常にノイズが多くなることです。



我々のアプローチは、フィルタリングされた重点サンプリングとKillzoneのアプローチの両方からアイデアを取り入れています。私たちは確率的にレイを発射しますが、そこそこ風変りなカーネルを使いますが、画像空間でフィルタリングも行います。


我々は、サーフェイスから方向を重点サンプリングすることから始めますが、発射するレイはごくわずかで、1ピクセルに1本という場合もあります。



大きな違いは、色をすぐに返すのではなく、交点をかろうじて保存している点です。

その後、「resolve」パスがあり、隣接するピクセル間でこれらの交点を再利用します。



再利用の間、近似コーンフィットを使用し、反射距離を考慮に入れて、各サンプルの望ましいブラーレベルを計算します。

各ピクセルのBRDFによる寄与を注意深く計量することで、法線の不鮮明さ、過度のぼかしを回避し、シャープな接触点を保持します。



これが結果のスクリーンショットです。後でビデオもお見せします。













さて、(できれば)結果を気に入ってもらえたところで、アルゴリズムのブレークダウンを見てみましょう。

まず、画面のどの領域に反射が必要かを分類し、各タイルにどれだけの作業を費やす必要があるかを見積もることから始めます。
次に、レイを適応的に割り当て、それらを重点サンプリングします。
次に、2種類のレイトレーシングを実行します。
すべてのレイトレーシングが終わった後、レイ再利用フィルタを使って色をリゾルブします。
最後に、前のフレームの結果を再投影し、結果をブレンドします。このテンポラルフィルタにより、ノイズが大幅に減少します。



さらに深く、すべてのステップを詳しく見てみましょう。

最初のものはタイルベースの分類です。画面を正方形のタイルに細分化し、各タイルに必要なレイの数を推定します。ピクセルごとに発射すべきレイの数の最小値と最大値をユーザーに指定させ、このパスで最小値と最大値の間で値を決定します。そのために、各タイルのレイを実際にトレースし、反射の知覚的分散を推測します。これにより、画像内のコントラストが際立ち、反射がよりノイズが多いと推定される場所に作業を割り当てます。また、生成されたレイが何も当たらない場合は、それ以降の計算からタイルを近似的にスキップします。



SSRが必要なタイルがわかったら、各ピクセルにどのようなレイトレーシングが必要かを決定するインダイレクトコンピュートパスを起動します。2つのレイトレーシング・アルゴリズムがあります。

1つは超精密な階層Zトレーサーで、正確な交点が得られます。鏡のような反射の場合、交点をできるだけ正確にしたいので、滑らかなサーフェイスにはこれを使います。

荒い反射の場合は、低品質のリニアマーチャーでごまかします。というのも、結果はいずれにせよ大きくフィルタリングされ、正確な交点はそれほど重要ではないからです。


階層トレースについて簡単にメモしておきます。その説明はGPU Pro 5のYasinの記事[Uludag14]や他のいくつかの出版物[Pearce15] [Hermanns15]にありますが、ここでも触れておいた方がいいでしょう。考え方は非常に単純です。min-zピラミッドがあり、これは基本的に4分木です。


私たちは階層の最も洗練されたレベルから始めます。ある瞬間にどのレベルにいるかに関係なく、レイをセルの端まで、またはセル内のZ平面と交差するまでステップさせます。Z平面に当たらなければ、より粗いレベルに移動します。



これにより、効率よく何もない空間スキップが可能になります。



Z平面との交点を見つけたら、より細かい階層に移動します。



…繰り返します。



…もう一度繰り返します。



最も粗いレベルでZ平面に当たれば、交点を見つけたことになります。



重点サンプリングについて前にも触れましたが、その概念について本質的にはなじみが無いかもしれません。

重点サンプリングは、モンテカルロ積分の分散を減らすテクニックです。

この関数を積分したいとします。サンプルを生成できる確率分布が必要です。それは、積分する元の関数にできるだけ近いものでなければなりません。

PDFからサンプルを生成し、それぞれについて関数の値とPDFの値の比を計算します。サンプルの数が増えるにつれて、それらの値の平均が被積分関数の値に近づきます。



レイの方向を生成するために、BRDFの重点サンプリングを使用します。ここではどんなBRDFでも使うことができますが、我々はたまたまGGXを敬愛しています。

さて、お粗末なレイは生成できません。レイトレーシングにはコストがかかるので、非常に良いレイを生成するために余分な労力を費やします。最低限、ハルトン・サンプラーを使用し、CPU側で事前に計算された値を使用します。

さて、BRDFの重点サンプリングの古典的な方法は、半角ベクトルを生成し、それをマイクロファセット法線に反射させることで動作します。この結果、いくつかのレイは実際にサーフェイスより下を向くことになります。そのようなレイは使えないので、良いレイが得られるまで何度か生成し直します。ここでの余分なコストは、実際には無視できるほど小さいです。

さらに進んで、Eric HeitzとEugene D’Eonが提案したように、可視法線分布から重点サンプリングすることもできます。これはおそらくノイズをかなり減らすことができるでしょう。そして,これは確かに我々の今後の課題です。



レイトレーシングをすべて実行したら、次は画像の色を計算します。

最も単純な方法は、各ピクセルのレイの交点で色をルックアップすることです。しかし、ノイズのない結果を得るためには、ピクセルごとにたくさんのレイが必要になります。

しかし、たいていの場合、隣接するピクセルからレイを盗むことができる。通常、サーフェイス特性は類似しており、視認性はほぼ常に同じです。従って、隣接するレイはローカルピクセルから射出されたことにして、それらの交点を使用します。



もちろん、交点を恣意的に再利用することはできません。正しい結果が得られるように注意する必要があります。すべてのレイの寄与は、現在のピクセルのBRDFで正しく重み付けされ、それらがサンプリングされたPDFで割られる必要があります。

…そして、私たちが楽観的すぎたことが判明します。近傍の確率分布は、ローカルピクセルのBRDF値とかなり異なることがあり、pdfに対するfの比率にかなり大きなスパイクを引き起こします。



ラフネスと法線のばらつきがあるシーンの例を見てみましょう。



ここでは、1ピクセルにつき1本のレイをハーフ解像度で計算し、レイの再利用を行わずに、反射だけを表示しています。



そしてここでは、リゾルブパスで4本のレイを使用しています。いくつかのサーフェスは滑らかになりましたが、地面のいたるところに高輝度の斑点がたくさんあります。全体として、これはレイを再利用しない場合よりも悪い結果です。



解決することは可能ですが、まずは一歩引いて、我々がここで解決しようとしていることはいったい何なのかを考えてみる必要があります。



これは散乱積分のバージョンで、簡潔にするために放出された光は削除されています。反射の値は、BRDFによって重み付けされた入射放射輝度の半球積分によって決定されます。



ここでは、BRDFと余弦項をPDF値で割ったものが分散の原因となります。すべてのサンプルを合計した後、これらの比率のスパイクは、過度に明るいまたは暗い色を持つピクセルになります。



すぐに明らかになるように、我々は分散問題を直接取り組みます。元の散乱方程式を取り出し、分子と分母に同じ値を掛けます。それがゼロでない限り、これは恒等式変換です。



次に、積分の1つを、オフラインで事前に計算できる定数に置き換えます。あなたのエンジンでは、すでにこの値を計算している可能性があります。これは、イメージベースドライティングのための分割積分定式化に通常使用するものと同じです。例えば、2013年のPhysically Based RenderingコースでのBrian Karisのプレゼンテーション[Karis13]を参照してください。



そして最後に、残りの部分をモンテカルロ求積法で計算します。



同じものを注釈付きでもう一度見てみましょう。これは基本的に加重和に帰結します。PDF値上のBRDFが重みとなり、最後にそれらの合計で結果を割ります。



コードも超シンプルに仕上がっています。



同じ画像をもう一度。まず、レイの再利用なし。



今度はレイの再利用で、新しい分散削減のトリックはなし。



そして,今度は分散削減付き。より良くなりました。



比較のために、これはレイの再利用なしですが、ピクセルあたり4本のレイを/トレースしています。より均一なノイズ分布のため、少しきれいに見えますが、それ以外の分散はかなり似ています。



たった一本のレイで、再使用はなしです。



そして,今度は分散削減付き。より良くなりました。



別の画像。ここでは1ピクセルあたり4本の光線をトレースし、4サンプルでリゾルブします。つまり、1ピクセルあたり4本のレイをトレースするだけで、16のカラー値が積分されます。いい感じになってきていますが、ノイズのない結果を得るにはまだコストがかかりすぎるようです。



……というわけで、最近みんなが気に入っている手法、テンポラル・フィルタリングを使うことにします。前の画像と同じような結果が得られるが、ここではまだ1ピクセルにつき1本のレイしか追跡していません。



重みを再正規化することで、もうひとつ素敵なことが出来ます。我々がやっていることは、たとえフィットの悪いレイがあったとしても、「BRDFの重みは積分して1にならなければならない」ということです。つまり、私たちは通常、近傍に使用できるレイを見つけることができます。たとえ、そのピクセル自身がレイをトレースしていなかったとしても。これによって可能になるのは、スパースレイトレーシングです。すべてのピクセルにレイを発射する必要はなく、フル解像度でリゾルブすればいいのです。いずれにせよ、私たちに適したレイを見つけることができます。そして、それらをフル解像度のBRDFで適切に重み付けします。



再度になりますが,これが最後の画像です。これは半分の解像度の結果です。



…そしてこちらはフル解像度でリゾルブしたものです。まだハーフ解像度でのレイトレーシングですが、フル解像度のディテールが得られます。

テンポラルフィルターはフル解像度での解像度を念頭に置いて設計されているため、ノイズもこちらの方が低くなっています。



テンポラルリプロジェクションについて触れたので、今度はそれを簡単に見てみましょう。考え方は簡単で、ピクセルの3D座標が与えられたら、それが前のフレームのどこにあったかをチェックし、それを投影すれば、サンプリングするテクスチャ座標が得られます。

…ただし、ビューポートを動かすと、反射に視差が生じます。つまり、反射オブジェクトは、それを反射するサーフェスの深度ではなく、その深度に従って動きます。より近い深度を使用して反射をリプロジェクションしようとすると、不鮮明になります。そこで、反射物の平均深度を計算し、それを使ってリプロジェクションします。その結果、スミアリングが大幅に減少します。



我々の重点サンプリングは、実際にはかなりたちが悪いです。かなりバイアスをかけています。膨大な数のサンプルを使用せずに、すべてのノイズを除去することは困難です。特にGGXのような分布の場合、その多くはBRDFのテールから来るものです。これが、生成されたサンプルをミラー方向にシフトさせる理由です。派手な言い方をすれば、重点サンプリングのために正確なPDF値が必要だからです。

逆関数法を使用する場合、「切り捨てられた分布」をサンプリングするのは、実際には非常に簡単です。

…オフセットを生成するために使われる擬似ランダム値をミラー方向からオフセットするだけです。

これは、「切り捨てられた」領域からのサンプルを、関数の「切り捨てられない」領域に比例して再配分する効果があります。PDFの値は、定数スケールファクター以外は同じです…そして、分散削減スキームがとにかくすべての定数ファクターを再正規化するので、それを計算する必要はありません。



私たちが使っているもうひとつの分散削減テクニックは、フィルタリングされた重点サンプリングです。「重点サンプリング」についてはすでに説明したので、フィルタリングの部分を追加するのは非常に簡単です。反射のために高周波数のカラーバッファをフェッチする代わりに、適切に事前にブラーたものを使います。トレースしたレイを円錐と見なして、交点でのフットプリントを推定します。そこから、使用する事前にブラーした画像ピラミッドのミップレベルを得ます。



事前ブラーされた画像レベルのサンプリングは、必要以上にぼかした反射を生成するバイアスをかけることができます。これは、反射を鋭くしすぎる重点サンプリングのバイアスに対抗するのに有効です。私たちはこの2つを一緒に配線し、最終的に1つの「バイアス」パラメータを持つようにします。このパラメータは、「純粋な不偏モンテカルロ」から、ミラー方向にトレースし、フィルターからすべての反射のぼかしを取るようになります。

バイアスを増やすと、2つの点で性能が向上します。レイトレーシングがよりコヒーレントになり、より小さなカラーミップをサンプリングします。スクリーン空間での近接は、反射での近接を必ずしも意味しないので、いくつかの不連続性とリークを導入するためです。バイアスを大きくすると、望ましい伸長効果も減少します。



これがバイアスをゼロにしたシーンです。



そして0.7でもう一度。反射の一部がわずかに変わりましたが、これはほとんどテンポラルフィルターの近傍クランプによるものです。それ以外は見た目は似ているが、ノイズが減り、性能が向上しています。



フル解像度のカラーリゾルブを覚えているでしょうか?実際には一度に4ピクセルずつ実行し、4ピクセルすべてに同じレイを再利用します。VGPRが重くなりますが、メモリ帯域幅を節約できるので、実際には得策です。レイデータをフェッチするのは4つのピクセルすべてについて1回だけでよく、ヒットポイントのスクリーン空間座標も同じなので1回計算するだけです。

しかし、必ずしも同じである必要がないのは、各ピクセルに対してフェッチするカラーバッファのミップレベルです。ピクセルは4つの異なるラフネス値を持つことができるので、異なるプレフィルター画像を使用する必要があります。ここでは、DXTフォーマットが色圧縮に使用するのと同様のトリックを使用します。4つのピクセルのアンカーミップレベルの最小値と最大値を求め、その間を補間します。こうすることで、カラーバッファのサンプルは4つではなく2つだけになります。



ミップアンカー補間が機能することを説明するために、ここにいくつかの比較画像を示します。下の画像では、4つのピクセルを1つのミップレベルで補間しています。そして上部には4つのユニークなミップレベルがあり、これが基準となります。真ん中が補間の結果です。ご覧の通り、違いはほとんど目立ちません。



PS4でのパフォーマンスを簡単にスライドにまとめました。ご覧の通り、レイの再利用スキームによって、レイトレーシングのコストをかなり効率的に削減することができます。








重点サンプリングノイズをフィルタリングしてみることもできます。Killzoneのアプローチがスクリーン空間での鏡のような反射をぼかすのと同様に、ノイズの多い反射をフィルタリングすることができます。ただ、サーフェイスのディテールを尊重する、よりスマートなフィルターが必要です。Yusuke Tokuyoshiは最近、ローブを考慮したフィルタリングに関するとてもクールな論文[Tokuyoshi15]を発表しました。彼はこれをパストレーシングとリアルタイムのコーントレーシングのノイズ除去に使っています。

画像はまず、重点サンプリングを使ってレンダリングされる。

次にフィルタリング処理は、フィットされた球面ガウシアンを使用することにより、出てくるスペキュラーローブの類似性を比較します。類似度はバイラテラルフィルタの重みとして機能します。

このアプローチは、接触硬化を除くほとんどすべての法案に適合します。ローブの類似性は物体の近接性を考慮しないため、物体間の鋭い接触が失われます。



Yasin UludagはGPU Pro 5でスクリーン空間の錐体トレーシングアルゴリズムを発表しました。
// Pearce15]と[Hermanns15]も参照してください。

このアルゴリズムは、円錐ではなくレイをトレースすることから始まります。

レイが何かに当たると、アルゴリズムはそれをコーンであるかのように見せかけ、事前にフィルタリングされたカラーバッファをサンプリングします。寄与は、事前にフィルタリングされた領域の計算されたカバレッジによって重み付けされます。

その後、完全なカバレッジが得られるまで、マーチし、より多くのサンプルを蓄積します。



問題はカバレッジの計算と、最初のヒットに続くトレースです。デプスバッファには、最初に見えるサーフェイスしか含まれていないので、オブジェクトの厚さは実際にはわかりません。ある程度の推測をするか、一定の厚みを仮定することはできます。しかし、アルゴリズムは、固い壁にぶつかっただけで、止まるべきなのか、ぶつかったものが薄い表面で、続けるべきなのか、まだわかりません。オブジェクトの背後をトレースできないので、最初のヒットの後のコーントレースも正確に実行できません。深度ピーリングを実行するか、シーン構造に関する他の情報が必要です。

全体として、単純なシーンでは、このアルゴリズムは素晴らしい結果を出しますが、取り除くのが難しい不連続性とアーチファクトを生成することがあります。






前に述べた積分前のFG項について、ちょっとメモしておきます。テンポラルフィルタをかけた後にFG項を乗算したほうが、FG項の変化が近傍クランピングに影響しません。また、事前積分された値はノイズフリーなので、リプロジェクションする必要もありません。

我々の場合、スクリーンにSSRを適用するパスにおいてFG項を乗算します。その値はイメージベースドベースのライトにも使用されるため、実質的に乗算演算は1回で済みます。



もうひとつ、マルチピクセルの解像について触れておかなければならないことがあります。4つのピクセルを同時に処理しますが、それは最も近い4つのピクセルではなありません。そうするとハーフレゾリューションノイズが発生し、Temporal AAは3×3の近傍領域でクランプするため、うまく機能しません。そこで、ピクセル間の距離がTAAウィンドウより大きくなるように画素を広げます。フレームごとに、どの4つのピクセルを一緒にリゾルブするかを変え、TAAにそれを解決させて滑らかな高解像度画像にします。



実は、Eric Veachの論文、特に多重点サンプリングに関する部分を読んでいて、レイの再利用のアイデアを思いつきました。私が得た洞察は、隣接するピクセルをレイ生成戦略として扱うことができるということです。そうすれば、PDFに対するBRDFの比率が高い、ありそうもないレイが出た場合、他の隣接ピクセルに「このレイを出す確率はどれくらいですか」と尋ね、ありそうもないレイの寄与を下げることができます。

このアプローチはうまくいき、素晴らしい結果が得られました。しかし、コストがかかりすぎました。注意深い計測のすべてはALUとVGPR地獄でした。



テンポラルスミアリングとラグを減らすために、近傍クランピングを使用します。これは、Brian Karis [Karis14]によるテンポラル・アンチエイリアシング・アルゴリズムに似ていますが、チューニングが少し異なります。ここでの値は一般的にもっとノイジーなので、カラーバウンディングボックスのクリッピングはTAAのように厳密にはできません。リゾルブパスでサンプリングする反射カラーバッファは前のフレームのものなので、いずれにせよリプロジェクションラグをすべて取り除くことはできないことがわかります。その点を考慮すると、近傍クランプにいくらかの緩みを与えても、ラグとスミアをわずかに増加させるだけです。