こんちゃわ、Pocolです。
今日は
[Narkowicz 2025] Krzysztof Narakowicz, Tiago Costa, “MegaLights: Stochastic Direct Lighting in Unreal Engine5”, SIGGRAPH 2025 Advances in Real-Time Rendering in Games course.
を読んでみようと思います。
いつもながら、誤字・誤訳があるかと思いますので,ご指摘いただける場合は正しい翻訳例とともに指摘していただけると幸いです。

こんにちは、私の名前はクリストフです。ティアゴ・コスタと共に、Unreal Engine 5における新しい「確率的直接光ライティング」技術をご紹介したいと思います。
ゲームは常に品質の限界を押し広げようとしている。より多くの光を使用したい、各光を動的にし影を落とさせたい、そしてリアルなソフトシャドウを持つエリアライトを実現したいと考えています。さらに複雑なBRDFや光源、あるいは複数のBRDF評価を必要とするレイヤーマテリアルを用いて、ライトがマテリアルレイヤーを通過する様子をシミュレートしたいとも考えています。しばしば、影のないライトの評価さえも計算コストが高くなりすぎるほどに。
ゲームが複雑化する一方で、ワークフローこそがグラフィック品質の主要な制約要因となっている段階に到達したと思います。理想的には、このスクリーンショットのように、アーティストが多くの制約なく遊び心を持って作業できるべきです。少しやりすぎかもしれませんが、まあ、アーティストがプロシージャルにライトを配置する方法を編み出した結果がこれなのです。
もう一つの重要なポイントは、これがベースラインとなるライティング技術でなければならないことです。アーティストが制作中に主要な視覚的目標として使用できるものでなければなりません。追加のライティングパスを必要とし、ワークフローを複雑化するような補助的な技術であってはなりません。少なくともコンソールと対応するPC GPUで動作する必要があります。
直接照明へのアプローチ方法は数多く存在します。
ゲームにおける一般的な手法は、フォワードライティングまたはディファードライティングを採用することです。画面上に表示される各光源について、まずシャドウマップやレイトレーシングによる影を用いて影項を事前計算し、ノイズ除去を施した上で影マスクを事前計算します。その後、別のパスで画面上に光を一つずつ適用し、事前に積分された放射輝度と計算された影項を組み合わせます。これは光源数が少ない場合には非常に効果的ですが、光源数が増えると光源ごとの処理コストが膨大になり、現実的ではなくなります。
オフラインレンダリングでより一般的な直接照明の別手法は、BRDFに基づいて、あるいは確率的に選択された光源群に向けて、固定数のレイをトレースし、光源に当たった場合にそのエネルギーを蓄積する方法です。ここでの主な利点は、パフォーマンスが照明の複雑さに依存しなくなる点です。各光源ごとに処理を行う代わりに、ピクセルごとに固定数のレイのみをトレースします。

ゲームにおける遅延ライティングの普及度を考慮し、我々はまずこの技術から調査を開始しました。レイトレーシングによる影や光の評価処理を高速化する方法を検討したが、期待した照明の複雑さには到底対応できませんでした。
内容を注意深く検証した結果、目標達成が困難な理由が明らかになりました。例えば、このピクセルは50個のライトの減衰範囲内にあり、各ライトに対してシャドウマップの計算、あるいはレイトレーシングとシャドウのノイズ除去が必要となります。しかし実際にこのピクセルに影響を与えるライトは15個のみでした。つまり、ここでは膨大な無駄な作業を行っていたのです。
このコストの一部はシャドウマップのキャッシュで隠蔽できますが、スケーリングにはほとんど影響しません。ライトやカメラ、オブジェクトの動きによるシャドウキャッシュの不整合が性能を損なう前にキャッシュできる量には限界があります。例えばMegaLightsデモでは、シーン内を飛び回るボットが数百もの移動光源を生成し、あらゆるキャッシュ方式を完全に無効化します。さらに、仮に全てが静的であっても、シャドウマップページのキャッシュには非現実的な量のメモリが必要となります。当社のMegaLightsデモでは、VSM(仮想シャドウマップ)を有効化すると、シャドウマップ仮想ページキャッシュの最大割り当てサイズである4BGを消費しても、必要な光を全て収めきれず、様々なアーティファクトが発生します。
レイトレーシングによる影は、適応的トレーシング(ピクセルごとまたはタイルごとのトレース回数を調整)やメモリ節約のための疎な影マスクを使用することでコストの一部を隠蔽できるが、これも全体的なスケーリングを大きく変えるわけではありません。レイの追跡とノイズ除去は非常にコストが高く、光源ごとに処理を行うことで光源数に厳しく比較的小さな制限が生じる。
仮に何らかの方法でシャドーイングを無料で処理できたとしても、1ピクセルあたり多数のライトを評価する課題は残ります。理論上は15個のライトに過ぎませんが、それらは複雑なライトタイプと複雑なマテリアルであり、シャドーイングを無効にしてもコンソールでは処理コストが高すぎます。
15個の可視光を見ると、エネルギーの80%が単一の光源から来ています。ではなぜ50個の光源を力任せに計算しようとするのでしょうか?その単一光源を高精度で計算し、残りを近似すればよいのではないでしょうか?
もう一つのアプローチは、BRDFサンプリングを使用するか、基本的にこれをGI問題とすることです。
UE5では一般的な回避策です。アーティストはシーンに何らかのエミッシブメッシュを配置し、メインビューから非表示にして、解析ライトの代わりにソフトなエリアライトとして使用します。
これは基本的に無料です。なぜなら、いずれにせよGIを計算する必要があるからです。しかし、多くの品質上の問題が伴います。小さな放射面や遠くにある放射面は、BRDFをサンプリングするだけでは、たとえLumen(当社のGI/反射システム)のレイガイディング技術で補強された場合でも、見つけるのが非常に困難です。
もう一つの問題は、リアルタイムGIがしばしば直接光による補助を必要とすることです。オフラインレンダリングでさえ、アーティストはGIの収束を早めるために窓にエリアライトを配置するといった手法を用いることが多い。ここではリアルタイムGIを、コンソールで60Hzで実現している。解析的な光でGIを補助する代わりに、直接光も同時に計算するよう要求しています。
第三のアプローチは、新しいシステムを構築することです。ここでは、ピクセルごとにランダムに固定された光源のサブセットを選択し、それらに向けて光線を追跡します。光線が光源に当たった場合、その当たり部分をシェーディングし、単一のレンダリングターゲットに光エネルギーを蓄積します。最後に、すべてのレイトレーシングが完了した後、そのレンダリングターゲットのノイズ除去を行います。この方法は、シーン内の光源数がどれほど多くても、ピクセルごとに常に固定量の処理を行うため、はるかに優れたスケーラビリティを実現します。
もちろん実際にはそれほど単純ではありません。コンソールではおそらく1ピクセルあたり1本のレイしか処理できず、その場合、各レイの使用効率を最大化したいのでライト選択が極めて重要になります。例えば、右のこの図では2つの光源に向けて2本のレイを追跡しましたが、これらはシェーディングポイントに非常に近く、非常に重要そうに見えました。しかし、どちらも遮蔽されているため、何も計算せずに光線予算をすべて無駄にしてしまいました。
ライトを選ぶ方法はたくさんあります。
最も一般的な手法の一つが、様々な種類のライト階層構造です。まずライトを中心に階層構造を構築し、その後最も重要なクラスターを選定します。事前構築された階層構造はライトサンプリングを高速化しますが、可視性を考慮していません。この図からわかるように、可視性はライト選択において極めて重要な要素です。ライト階層化はライトの統合(階層的LOD)も可能にしますが、実際には多くの問題(不正確な照明、リークなど)が発生します。さらに、このライト階層化を毎フレーム構築するのは非常にコストがかかり、この処理はGPUへの適応が困難です。
もう一つの非常に人気のある手法がReSTIRです。高性能PCでは驚くべき結果を出せますが、これをコンソール向けにスケールダウンし、ベースラインとなるライティング手法にできるでしょうか?
その質問に答えるためには、まずReSTIRが実際に何を行うのかを確認する必要があります。
ReSTIRは、確率的直接照明にこれらの数個のオレンジ色のブロックを追加します。これは、履歴と近隣から数個のサンプルを検索し、光線追跡によってそれらの可視性を確認し、最終的に再利用されたサンプルと、このフレームで確率的に選択された新しい候補サンプルを組み合わせます。
ここでの主な考え方は、例えば選択したサンプルがすべて遮蔽されていた場合のように、確率的に良い候補サンプルを選べない場合、履歴の中に何かより良いものがあるか、あるいは隣接ピクセルの方が光の選択でより幸運だった可能性があるということです。
ReSTIRは品質を大幅に向上させるが、欠点は再利用により高い定数コストが発生することだ。再利用操作自体がコスト高であるだけでなく、最も重要なのは再利用された各サンプルの可視性をレイトレーシングで確認しなければならない点である。
妥当な品質を達成するためには、少なくとも1回のSPP(単一光線追跡)が必要であり、これには1ピクセルあたり2~3回の光線追跡が求められます。高性能PCでは問題ないかもしれませんが、コンソールでは1ピクセルあたり1光線以上の追跡は現実的に不可能です。
もう一つの問題は候補のサンプリングである。
理論上はピクセルごとに完全にランダムな光を選択することも可能ですが、実際には出荷可能な品質を達成するためには、それらの光を非常に慎重に選択する必要があります。各光源にはBRDFによる重み付けが必要であり、ピクセルごとに光源リストの少なくとも20%を評価できる必要があります。ハイエンドPCでは大した問題ではないかもしれませんが、コンソールではこのコストが急速に累積します。なぜなら、シーン内の光源の20%に対して影のない光源評価を実質的に行っていることになるからです。
さらに、BRDFは遮蔽を考慮しないため、強い遮蔽光は大量のサンプルを必要とし、良好な可視光を見つけることがさらに困難になる。
要するに、我々は既に負担しきれない高い固定コストを抱えつつ、以前と同様の軽いサンプリング問題を、単に定数が異なるだけで解決しなければならない。
では良い質問です——ReSTIRよりも優れた方法はあるでしょうか?
確率的ライトサンプリングを試行錯誤している際、単純なサンプリングの方がReSTIRよりも効果的な場合があることに気づきました。その理由は極めて単純です。初期サンプルは繰り返しされる確率が非常に高く、各フレームごとに初期サンプルと現在のフレームサンプルを結ぶ経路が指数関数的に増加するためです。これが、実際のReSTIR実装でM(サンプル履歴を保持するフレーム数)を制限する理由ですが、制限してもこのクラスタリング効果は顕著に残ります。これを修正するにはMを1に制限する必要があり、これにより再利用が事実上無効化され、単純な確率的サンプリングに回帰することになります。繰り返されるサンプルの塊はReSTIRの出力をノイズの少ないものにしますが、同時にノイズ除去の有効性も大幅に低下させます。ノイズ除去が最適に機能するためには、相関がなく交互に現れる光のパターンが望ましいのです。
別の見方をすれば、ReSTIRとデノイザーはどちらも非常に類似したスクリーンスペース空間・時間フィルタリングを行っている。違いは、ReSTIRが既にシェーディングされたサンプルを再利用するのではなく再利用されたサンプルを再シェーディングすること、より長い時間履歴(通常2倍)を持ち、それらのサンプルが履歴補正を経る必要がない点にある。これによりReSTIRはより多くの時間フレームを蓄積し、より積極的に近傍サンプルを再利用できるが、同時にサンプリングパターンを乱すため、場合によっては全体の画質低下を招くこともある。
では、時空間再利用を省略し、代わりにデノイザーのサンプリングを設計して、同様の品質をはるかに低コストで実現し、制約のある目標予算内に収めるのはどうだろうか?
理想的には、各ピクセルごとに可視光リストをサンプリングするだけで済む。
このようなリストがあれば、各フレームごとに異なる光を確率的に選択でき、ノイズ除去器に美しいパターンを生成させることが可能となる。
可視光のみをサンプリングすれば、最終的なピクセルに寄与せず、サンプリング予算を浪費しノイズを増大させるだけの隠れた光源への追跡作業を無駄にすることがなくなる。

ヒストリーデータは、このような可視光リストの優れた情報源となり得る。なぜなら、前フレームで可視だったサンプルは、おそらく次フレームでも可視である可能性が高いからである。
メモリオーバーヘッドのため、ピクセル単位のライトリストは現実的ではありませんが、8×8の画面空間タイル単位であれば実現可能です。隣接ピクセルはライト可視性を共有する確率が高い。このリスト作成のため、トレーシング処理後に可視光サンプルを全て収集し、WaveActiveMin出力で8×8タイルごとのソート済み光ライトストを生成する。次のフレームでは、サンプリング処理でピクセルを再投影し、該当タイルを検索して可視光リストから光源を選択できる。
二値可視化に代わる様々なダウンウェイト方式も試しました。各光源を光線ヒット/ミス調整比率で重み付けする手法ですが、実際には効果が低かったのです。こうした方式では半影領域のサンプルに対する光線追跡数が減少するためです。通常はむしろ逆の効果が望まれます。半影領域はノイズが多く、そこでのサンプリング不足は避けたいからです。
8×8タイルはかなり大きく、時に目に見える不連続性を生じさせます。本質的に、ここではタイル境界で一つの光リストから別のリストへ切り替わっています。これを修正するため、確率的双線形補間を使用します。これにより、最も近い4つのリスト間で滑らかに補間が行われます。これにより、これらの遷移を隠すだけでなく、画面上で新たに可視化された光の伝播を高速化します。
8×8のスクリーンスペースタイルは深度不連続面におけるサンプルガイディングの効果を低下させるが、実際にはピクセル単位で光の可視性を蓄積するため、それほど悪影響はない。
当初はブルームフィルタを使用していました。これは興味深い手法です。ブルームフィルタは独創的なデータ構造であると同時に、リアルタイムレンダリングではあまり一般的ではないからです。その後、明示的なリストに切り替えました。これにより、各ライトごとに追加のペイロードを保持できるようになり、ライトグリッドセル内の全てのライトを反復処理することなく、そのようなリストをサンプリングできるからです。
これらのリストには小さな固定サイズが設定される場合もある。基本的にその長さは、8×8タイルごとに可視となるサンプル数によって制限されるからだ。別の見方をすれば、1SPPをシェーディングする場合、デノイザーでの時間的蓄積があっても(光の選択方法に関わらず)蓄積できる光の数は限られる。つまり、タイルごとの可視光の最大数は、ピクセルごとのシェーディングサンプル数によって制限されるということだ。
可視光リストのみをサンプリングすることはできません。シーンは動的であり、隠れた光が可視化される可能性があります。サンプリング予算の一部を、新たな可視光の発見に充てる必要があります。
ここでは、可視光リストと隠れた光リストの両方からサンプリングを行い、隠れた光リストの重み合計を総重み合計の20%に制限します。これにより、隠れた光に対して固定数のサンプルを割り当てることが可能となります。
可視光を1つのリザーバーに、隠れた光を別のリザーバーにサンプリングし、両者を統合する直前に隠れたライトリザーバーの重みをクランプすることで、これを非常に容易に実現できる。両リザーバーは独立した乱数変数を使用するため、相関が生じない。また、可視光リストの乱数変数に基づいて隠れたライトリザーバーを追加することで、可視光リストの乱数変数のノイズ特性を維持できる。
20%は当然ながら任意に調整可能な数値であり、収束後の品質と離脱時の品質/シーン変化に対する手法の反応速度とのトレードオフを制御する。
可視光が非常に暗かったり、局所的な光源が全く存在しない場合もある。そのような状況では、20%クランプを緩和することで、隠れた光源へ向けたより多くの光線追跡を可能にし、シーン変更時や遮蔽解除時の収束速度を向上させる。
隠れたライトの予算を調整する方が、隠れたライトの重みを下げるよりも効果的です。なぜなら、強い隠れたライトはサンプリングを支配すること(サンプル予算の20%を超えること)が決してないからです。当手法は、通常ならサンプリングを支配してノイズを大量に発生させるような、完全に遮蔽された強いライトといった困難なケースに対処するのに非常に優れています。
オブジェクトの移動や画面外サンプリングにより、歴史の再投影が失敗する場合があります。その場合でも、有用な光が含まれている可能性が高い最寄りのタイルを再利用しますが、新たに可視化された光の検出を高速化するため、隠れた光サンプルの比率も増加させます。
この可視光リストが得られたところで、新しいパイプラインを見てみましょう。以前見たものとほぼ似ていますが、可視光リストを構築する役割を担うこのオレンジ色のブロックが追加されています。次のフレームでは、このリストが光のサンプリングに使用され、リスト構築のわずかなコストでサンプルを誘導することが可能になります。
隠れた光をチェックするために一部のトレースを割り当てていますが、これは比較的小さなオーバーヘッドです。ほとんどの光線は可視光に向けて送信され、最終的なピクセル生成に寄与しています。
ついにライトリストが完成しました。これでデノイザー用の美しいパターンを生成できます。
それでは、このライトリストをうまく活用しましょう。
サンプルを選択するために、我々は重み付きリザーバーサンプリングを使用します。下図でわかるように、これは全てのライトを一度ループ処理し、その重みに基づいて確率的に1つを選ぶという非常に単純な手法です。
各光源をBRDFの輝度で重み付けし、知覚重み付けには対数関数を用いる。知覚重み付けは一般的な画質向上効果をもたらすが、最も重要なのは、トーンマッピング後に最終ピクセルへの影響が小さくなる非常に強い光源の重みを下げられる点である。これにより、強い遮蔽光の問題を緩和できます。
時空間ブルーノイズは、ノイズ除去に最適化されたノイズパターンを備えたルックアップテクスチャを提供します。これらのパターンは非常に優れており(かつ低コスト)、画面空間における様々な確率的操作のためにエンジン全体で使用されています。
ここで一つだけ小さな問題があります。このルックアップテクスチャは各ピクセルに対して単一の乱数変数を提供しますが、ここでお分かりのように、サンプル選択ループの各反復ごとに1つの乱数変数が必要です。STBNテクスチャを複数回サンプリングすることはできません。なぜなら、このテクスチャはSTBNパターンの優れた特性を維持するために、各ピクセルに対して1回だけサンプリングされるよう特別に事前計算されているからです。
幸いなことに、元のノイズ特性を維持したまま、確率変数を複数回再利用するためのいくつかの手法が存在します。
単一サンプル選択では、各光選択ステップ後に選択範囲を0-1に再マッピングできます。
ピクセルごとに複数の光線をトレースしたい場合、ディザリングサンプリングを使用できます。これにより、ランダム変数を複数のセグメントに再マッピングします。
いかなる再マッピングも、我々の乱数変数の精度を1ビット消費するが、実際には問題にならない。可視光リスト用と隠蔽光リスト用の2つの乱数変数を用いてサンプリングするため、このビット損失を2つの乱数変数に分散できる。さらに、パフォーマンス上の制約から、いずれにせよリストごとにループ処理できる光の数には限界がある。

これらすべてにより、単一のテクスチャルックアップでより高速にサンプリングできるだけでなく、最も重要なのは優れたSTBN特性を維持できる点です。これは大幅な品質向上であり、しかも完全に無料です——追加の計算やトレースを一切必要としません。

ライトの選択方法は理解できたが、大規模なシーンではライトグリッドセル内の全ライトをループ処理するのは非常にコストがかかる。これらのライトグリッドセルには数百ものライトが含まれる可能性がある。
ここでは、可視光リスト上の全ての照明を評価した後、可視光リストで既に評価済みの照明をスキップしつつ、照明グリッドから一部の照明を評価します。各ピクセルが異なる確率的サブセットを評価するため、相関性は低いものの、光の変化を素早く捉える効果は高いです。履歴の欠落を検知した場合、照明グリッドセルから評価対象とする照明の数を増加させます。
アルゴリズム全体は、異なるストライドを持つ2つのソート済みライトリストを反復処理し、両リストの最小ライトインデックスを評価することに帰着する。
ここでできるもう一つの簡単な最適化は、BRDFの輝度のみが必要だということです。入力全体をグレースケールに変換する完全なグレースケールBRDF計算はノイズを過剰に追加することが判明しましたが、光成分アキュムレータなどのコードの一部をグレースケールに変更することでVGPRの使用量を削減できました。
また、特定の露出相対閾値を下回るサンプルも破棄します。この閾値はかなり低く設定されているため、バイアス(エネルギー損失)をほとんど引き起こしません。これはパフォーマンス最適化ではありませんが、品質向上には役立ちます。基本的に、最終的なピクセルに影響を与えるほど強くない光については、その可視性を確認するために光線を無駄にする代わりに、より重要な処理に割り当てることができます。これにより、非常に発生確率が低く微弱な光源から生じるファイアフライ現象も除去されます。この現象は、特定のフレームではかなり大きな重み付けを受ける可能性があります。
ピクセル間で法線と深度が類似している場合、ライトウェイトは通常かなり似通っています。この性質を利用して、より低い解像度でサンプリングできます。例えば、ピクセルごとに1サンプル選択する代わりに、BRDF計算を再利用しながら4ピクセルごとに4サンプルを選択できます。
ここで重要なのは、チェッカーボード法や4ルーク法のような優れたサンプリングパターンを使用する必要がある点です。さらに、それらのサンプリングパターンを空間的・時間的にジッタリングします。これら全てが最終的なピクセルを再構築する可能性を大幅に高めます。
サンプリング後、深度と法線重みに基づく確率的双線形アップサンプリングを行い、最終的には正しい結果に収束するはずです。
ごく稀なケースでは、アップサンプリング元の有効なピクセルが存在しない場合があります。深度が深すぎる、あるいは法線が不連続であるために、全ての重みがゼロになる可能性があるためです。例えば、細いワイヤーが存在し、それに属するピクセルを全くサンプリングできていない場合が考えられます。そのような場合、近傍クランプなどの履歴補正を一切行わず、履歴をそのまま再利用します。
ヒストリー補正とアップサンプリングにより、この手法はフルスクリーンサンプリングと同じ結果に収束せず、影をやや柔らかく(フル解像度とハーフ解像度の中間程度に)表現することがあります。一方でサンプリング速度がほぼ4倍高速化されるため、実用上はかなり良いトレードオフとなります。
現在、フル解像度サンプリングの品質を維持しつつ低解像度サンプリングのパフォーマンスを向上させるため、これを適応型サンプリング方式に変更する作業を進めています。

ディレクショナルライトは確率的ライトサンプリングに多くの問題を引き起こす可能性があります。
ディレクショナルライトは通常、非常に強力な光源であり、シーン内の他の光源よりも数千倍も強い場合が多い。BRDFに基づくサンプリングでは、こうした光源は非常に高い重みを持つことになる。つまり、光選択の過程でほぼ全ての光線をその光源に向けて送り、局所光源にはほとんど光線が割り当てられない。これは、室内空間で新たな可視光源を発見しようとする際に問題となる可能性がある。
一般的な解決策としては、ディレクショナルライトを別のパスで計算する方法があります。例えば、ディレク疎なるライト専用のレイトレーシングによる影パスを実行します。この別パスは品質向上にも寄与します。ディレクショナルライト専用にシェーディングとノイズ除去のパスを実行できるためです。欠点は、これがかなりコストがかかる可能性があることです。ピクセルごとに追加のレイをトレースし、別のシェーディングとノイズ除去パスを実行する必要が生じるためです。また、制約のあるゲーム予算に常に収まるとは限りません。
代わりに、ディレクショナルライトに使用できるサンプル予算の一部を制限します。これは隠れたライトと非常に似ており、ディレクショナルライトの重みをローカルライトの重み合計の%にクランプします。この処理は、ローカルライトの重み合計が特定の閾値を超えた場合にのみ適用されます。これにより、ローカルライトが存在しない場合や非常に弱い場合、固定の50%予算よりも多くのサンプルをディレクショナルライトに割り当てることが可能になります。
この手法は本質的にソフトレイ予算として機能し、特定のピクセルに影響を与える局所的な光に応じて、ディレクショナルに向けてより多くまたはより少ないレイをトレースすることがある。
他のディレクショナルライトも同様の問題を抱える可能性があります。例えば、太陽を模した非常に強力なスポットライトを使用する場合などです。実際にはそのような問題は発生しませんでした。太陽より弱い光源は通常、知覚重み付けだけで適切に処理されます。隠れた光予算を20%に制限することも、こうした光源の処理を改善します。これにより、最大でも20%の光線しか受け取らないことを保証できるからです。理論上は、この方式を拡張して非常に強力なライトの一覧を選択し、それら専用の予算を設定することも可能です。
もう一つ確認すべき点はエリアライトです。
このスクリーンショットでわかるように、それらはかなり大きく、単純な二値光の可視性だけでは不十分です。そのような光の大部分は遮蔽される可能性があり、それに向かってトレースするサンプルを無駄にすることになります。
これを改善するため、各光の可視部分をマークする追加の2×2ビットマスクを保持します。このビットマスクは可視光リスト内の単なるペイロードであり、可視光リストと共に構築されます。
より具体的に言えば、2×2ビットマスクはエリアライトサンプリングに使用される2次元乱数変数を細分化します。エリアライトサンプリング関数は、生成されるサンプルの品質を最大化するため、面積を保持したまま、その2次元乱数変数を[0;1]の正方形から光源領域へ再マッピングするように設計されています。この方法により、あらゆる光源(カプセル、球体など)に対して非常に良好に機能します。
固定の2×2分割は全ての状況に最適とは限りません。光源が非常に大きい場合など、より細かい分割が必要なケースもあります。また、ラインライトのようなケースでは4×1のような異なる分割比率が望ましい場合もあります。現在、これを適応的で階層的な方式に改良する作業を進めています。

サンプリング時には、まずピクセルごとにN個の光源を選択し、次に選択された各光源について、その表面上の点を選択する必要があります。
この点選択により隠れた領域の重み付けが低下し、光の可視部分に向けてより多くの光線を追跡できるようになるため、ノイズが低減されます。
各エリアライトは、隠れた領域の重み付けを下げた後も良好なSTBN特性を維持するため、2次元サンプルワーピングを伴う2次元STBNノイズを用いてサンプリングされる。これらは以前見たSTBNやワープとは若干異なる手法であり、今回は2次元点で処理しているためである。
サンプリングの確率的性質により、一部の光線が重複する場合があります。
例えば、表面近くに強力な点光源があり、同じピクセルからその一点光源に向けて4本の同一の光線をトレースする場合を考えます。実際には4本全てをトレースする必要はありません。1本だけをトレースし、その可視性を他の3本に再利用できます。
これは、非常に小さな面積を持つ遠方の光源でも発生する可能性があり、その場合、半影が小さすぎるためである。
コンテンツではあまり一般的ではありませんが、アーティストは大面積ライトを好んで使用します。しかし、これにはデメリットがなく、パフォーマンスを多少向上させることができます。
また、グローバルな半影サイズ乗数を調整してさらに縮小することも可能です。このパフォーマンススケーラビリティ乗数は、エリア光源サイズを縮小するため照明の見た目を変化させますが、同時にトレース速度も向上させます。より多くの光線が重複してスキップされるためです。これはSteam Deckやハイエンドモバイル端末など、現行世代のコンソールよりはるかに低速なプラットフォームにおいて有効なトレードオフとなり得ます。アーティストによる手動でのシーン再照明を必要とせず、現行コンソールと同等のコンテンツを実行可能にするためです。
現行世代のコンソール以下に自動的にスケールダウンする別の方法は、ピクセル間で光線を再利用することである。
中央のサンプルを単にシェーディングする代わりに、いくつかの近傍を調べて、それらの光線を再利用できるかどうかを確認できます。
我々はスクリーンスペースカーネルを使用しており、そのサイズは当該ピクセルまでの距離と光線ヒット距離に基づいて決定される。また、ピクセル間の深度差といったいくつかのヒューリスティックも確認する。
最終結果も再重み付けが必要である。なぜなら、隣接ピクセルでは中心ピクセルとは異なる確率で選択されるためである。
接触影を若干ぼやけさせますが、ピクセルあたりの光線計算量を削減しつつ、照明の安定性とシャープさを維持できます。
ついに可視サンプルの陰影付けの準備が整いました。
まず、特定のピクセルに影響を与える可視サンプル重みを累積します。次に、この累積重みを事前積分された光照度(解析的/事前計算された光照明)で乗算します。
事前統合済み放射照度を使用することは、遮蔽と陰影を分離できると仮定することを意味しますが、これは正しくない([Heitz et al. 2018]の序論にはこの近似とその問題点について優れた説明がある)。しかしこれにより、処理速度が若干向上し、ノイズが低減される。
最も重要なのは、後方互換性を実現できる点です。当社の確率的照明は非確率的照明と全く同じ見た目になるためです。これはハイエンドPC向けReSTIR実装でこの近似法を採用する理由でもあります。
とはいえ、これはいずれ対応すべき課題です。ゲーム以外の用途ではよくある要望だからです。
シェーディング処理の後、ノイズ除去を実行します。
TSRだけでもかなり良い結果が出ていますが、一部の箇所では専用のノイズ除去処理が確実に必要です。
全ての光源に対して1回のノイズ除去処理を実行し(全ての照明は2つのレンダリングターゲットに集約される)、拡散信号と鏡面反射信号を別々にノイズ除去する。
ノイズ除去の前に信号を復調します。これは信号から非確率的な物質成分を除去する作業です。アルベドのような物質データをぼかすことは望ましくありません。
このデノイザー全体は、SVGFによって導入された時間的分散の概念に基づいています。信号の時間的分散を追跡し、後でその値をピクセルの雑音量の指標として使用します。これにより、そのピクセルに必要な強力な空間フィルタリングを把握できます。この方法により、画像のノイズ部分のみをぼかすことが可能となります。
テンポラルフィルタ側では、ここで履歴を再投影し、照明と照明の瞬間を蓄積します。
照明は2つの32ビットレンダリングターゲットに保存されます。1つは拡散反射用、もう1つは鏡面反射信号用です。確率的浮動小数点量子化により32ビット精度のみを使用可能であり、これにより様々な縞模様や色ずれのアーティファクトを防止できます。実際には非常に良好に機能しており、64ビットの参照画像と比較しても問題は確認されていません。
また、照明輝度の第1モーメントと第2モーメントも保存します。これも同様に、拡散光用と鏡面反射光用のモーメントをそれぞれ1セットずつ保存します。
Float11とFloat16はかなり広い範囲(-2^16から2^16)を持ちますが、それでも極端なケースでは範囲を超える可能性があります。クリッピングによる問題を防止するため、全ての照明値はプリエクスポーズ空間に格納します。
ヒストリー補正には5×5近傍クランプを使用します。これはかなり広い領域なので、まず全てを読み込んでグループ共有メモリに格納します。
YCoCg空間でバリアンスクリッピングを実行し、履歴補正時の色ずれを低減します。
興味深い手法の一つは、新しいデータが近傍境界の外側にある場合、その境界からの距離に基づいて履歴の処理を高速化することで、ゴースト現象を大幅に低減することです。ここでの考え方は、新しいデータが履歴から非常に離れている場合、その履歴を修正して再利用しようとするよりも、むしろ素早く破棄すべきである可能性が高いということです。具体的な計算方法は以下の通りです:
float3 ClampedHistoryDiffuseLighting = clamp(HistoryDiffuseLighting,
DiffuseNeighborhood.Center - DiffuseNeighborhood.Extent,
DiffuseNeighborhood.Center + DiffuseNeighborhood.Extent);
float NormalizedDistanceToNeighborhood = length(
abs(ClampedHistoryDiffuseLighting - HistoryDiffuseLighting) / max(DiffuseNeighborhood.Extent, 0.1f));
float DiffuseConfidence = saturate(1.0f - NormalizedDistanceToNeighborhood);
DiffuseConfidenceは後段で、履歴に蓄積される最大フレーム数を削減するために使用されます(履歴の重みを減らす)。急激な遷移を防ぐため、少なくとも数フレームの履歴をブレンドインさせる必要があるため、0まで低下させることは許可しません。
もう一つは、ダウンサンプリングを使用する場合、一部のピクセルは再構築されるため信頼性が低くなるため、それらのピクセルに対して近傍クランプを緩和することです。これにより、幾何学的形状やサブピクセルジッタの影響で各フレーム入力が全く異なるように見える、高度に不連続な特徴(微細な金属格子など)における不安定性が解消されます。
最後に空間フィルタを適用し、時間フィルタ処理後に残存するノイズを除去します。このフィルタは履歴への時間積算後(履歴を通じた再帰的ぼかしなし)に実行されるため、遮蔽解除後にデータを積算するにつれて出力をより鮮明にし、正しい結果へ迅速に収束させることが可能となります。
空間フィルタは標準的なものとは少し異なります。高価なA-Trous処理を複数回行う代わりに、ピクセルごとに回転させる単一の疎カーネルを使用します。これはTSR(当社の時間的アンチエイリアシング+アップスケーラー)によって実現されており、フィルタの穴をすべて解消できます。
比較的時間的な変動が大きいピクセルにのみ適用するため、処理速度と解像度の両方が向上します。ここでは完全な画像を出力する必要はなく、一部のノイズはTSRで処理可能です。
絶対的な変動量を使用することは、強い鏡面反射照明のようなケースで有用です。このような場合、数値精度の問題により、たとえそれらのピクセルがノイズを含んでいなくても、わずかな誤差が大きな絶対的な時間的変動を引き起こす可能性があります。
ディスオクルージョン処理では、入力ピクセルの時間的分散が一定であると仮定する(分散推定の追加オーバーヘッドは割に合わないと判断)。空間サンプリング数を増やし、トーンマッピング空間で積算することでファイアフライを除去する。積算フレーム数を増やすにつれ、これらの仮定を段階的に解除する。4フレーム分の履歴データを積算後、ディスオクルージョン処理を完全に無効化する。
ノイズ除去にはもう一つ問題があり、ここで議論する必要があります。具体的には、ノイズ除去はアップサンプリングよりも低い解像度で蓄積およびフィルタリングされることです。
これは、ノイズ除去器の履歴における単一ピクセルが、アップサンプリング後の複数ピクセルに対応することを意味します。したがって、ノイズ除去時には、ぼやけた照明を引き起こす無関係なピクセルを蓄積するか、ノイズの原因となる各フレームの履歴を破棄する必要があります。
この問題は、ライトごとのノイズ除去ではそれほど顕著ではありません。それらはシャドウマスクや比率推定器を用いてシャドウ項のみを除去し、ライトは各フレームごとにピクセル単位で非確率的に評価されます。この場合、この問題は主に半影周辺でのみ目立ちます。複数の光源から合成された放射輝度をノイズ除去する場合、問題はより深刻です。全ての照明がぼやけ、特に人間の目が反射光の詳細不足を素早く感知する顔面では顕著に目立つためです。各光源ごとの比率推定器ノイズ除去と同様の手法として、ピクセルごとに最も重要な光源(BRDF)を特定し分離する試みも行いました。しかし光源選択自体が確率的であるため、複雑な照明環境ではこの選択ノイズが画面上に顕在化する結果となり、実用上効果的ではありませんでした。BRDFそのものを抽出する方法も理想的とは言えません。なぜなら、時間的・空間的なフィルタ処理が誤った値に対して行われるためです。各ピクセルが異なる重要光源で割られる可能性があり、最も重要な光源の選択が不連続な領域でそれらの値をブレンドしようとすると、奇妙なアーティファクトが発生する可能性があります。
理想的には、ノイズ除去処理の履歴も表示解像度で保持すべきであり、そうすればこの問題を回避できます。しかし実際には、コンソールではこの処理が非常に高コストになる可能性があります。1080pでレンダリングした後、4Kにアップサンプリングする手法は一般的です。この場合、ノイズ除去処理で4K解像度での時間的フィルタリングが必要となり、処理全体が約4倍遅くなります。少なくともハイエンドPC GPUへの拡張手段として、この点についてはさらに研究を進める価値があります。
前述のように、通常1ピクセルあたり重要な光はわずか数個しか存在しません。そしてピクセルのエネルギーの80%をサンプリングできれば、ノイズ除去量を削減できるか、あるいは信号を直接TSRに渡すことさえ可能になります。
そのためのかなり良い経験則があります。可視光リストは、特定のピクセルに影響を与え得るエネルギーの総量を示します。また、このフレームで正常にサンプリングできたものも把握しています。例えば、エネルギーの80%を占める強い鏡面反射を持つ光源が1つあり、それをこのフレームでサンプリングできた場合、ここではノイズ除去を実際に行う必要はなく、その信号を直接TSRに渡すことができます。
このヒューリスティック手法は、フレームごとにサンプリングされた光セットが大きく変化する可能性があるため、ある程度の時間的安定化(時間的蓄積)を必要とするが、実際には全体的に非常に良好に機能する。出力画像のシャープネス向上に寄与するだけでなく、特に非平面表面において正確な再投影が困難な、鏡面反射ハイライトのゴースト現象やぼやけといった一般的なノイズ除去問題の改善にも効果を発揮します。
ここからはわかりづらいかもしれませんが、右側の切り取った画像が実際により鮮明になっています。
それでは、ここでティアゴに引き継ぎます。
ライトサンプルの可視性を計算する主な手法としてハードウェアレイトレーシングを採用しています。これにより、フレームごとに複数のシャドウマップをレンダリング・維持するオーバーヘッドを回避でき、特に多数の動的光を扱う場合に生じる問題を解決できます。
影の品質は非常に重要ですが、メインビューのレンダリングに使用される詳細度でBVH内の全オブジェクトを表現することはできません。まず、頂点ごとのメモリオーバーヘッドが大きく、Naniteを利用するUEプロジェクトでは高精細メッシュが使用される傾向にあります。これはBVHの構築とトレース処理のコストが過大になることを意味し、さらにキットバッシュされた環境ではインスタンスの重複が多発するため、トレースコストがさらに増加します。
したがって代わりに、レイトレーシングにおけるレベル複雑度を低減するため、簡略化されたプロキシメッシュに加え、積極的なインスタンスカリングと集合表現を使用する必要があります。
レベルには2種類のレイトレーシング表現を使用します:
・プレイヤーカメラから半径150メートルの範囲である近距離領域では、プロキシメッシュを使用します。
○ これらは元のジオメトリを低ポリゴンで表現したもので、パフォーマンスと精度のバランスに優れ、近接トレースに最適です。
・レイが近距離フィールドメッシュに当たらず、その半径外に伸びた場合、より積極的に簡略化されたレベル表現に対してもトレースを行います。
○ この表現ではインスタンスを統合し、三角形数を大幅に削減することでレイ通過コストを抑えます。
○ 遠距離フィールド表現は別のTLASに保存されるため、BVHの複雑度が低くなりトレース速度が向上します。
現在の世代のコンソールではより優れたパフォーマンスが得られるため、デフォルトでインラインレイトレーシングを使用しています。
レイトレーシングにおけるプロキシメッシュの使用には、プロキシとラスタライズされたジオメトリ間の不一致という大きな欠点がある。

これらの不一致により、レイがラスタライズされたジオメトリ表面から追跡されるため、プロキシメッシュの三角形と直ちに交差する可能性があり、誤った自己影が生じます。
これらのスクリーンショットでは、プレイヤーの正面の壁に不正確な影が映っているのが確認できます。これは、そのメッシュがテッセレーションを使用しているためで、レイトレーシングでは効率的に表現できません。同様に床にも不一致が生じており、より多くの自己影を引き起こしています。さらにプレイヤーキャラクター自体にも、レイトレーシングでは適切に表現されないシミュレートされた布メッシュが存在し、不正確な影の原因となっています。
アニメーション処理やアルファマスク処理が施されたジオメトリには、従来からある課題も存在します。これらは正確に表現し、レイトレーシングを行う際に特に計算コストが高くなります。

残念ながら、これらの不一致の問題は、単にレイに対して前面または背面カリングを使用するだけでは回避できません。
左の図では、背面カリングだけで誤ったオクルージョンを防ぐのに十分であることがわかります。しかし右の図では、レイがプロキシの前面にも当たる状況が発生し、誤ったオクルージョンが生じていることがわかります。
さらに、前面または背面カリングを使用すると、レイのトラバース中に早期終了を妨げるため、トレース処理に約10%のオーバーヘッドが追加されます。
つまり、プロキシメッシュだけに頼るわけにはいかず、これらの問題を回避するための代替手段が必要だということだ。
したがって、誤った自己影を回避する主な手法は、スクリーンスペースレイトレーシングです。スクリーンレイはラスタライズされたジオメトリの深度バッファに対して追跡されるため、プロキシジオメトリと誤って交差することなく表面から離れることが保証されます。この図が示すように、ワールドトレースの原点をスクリーンレイの到達距離に基づいてオフセットすることで、自己影の問題の大半を回避できます。
もう一つの利点は、BVHでは表現されない詳細な接触影が得られることです。ただし、通常は少ないタップ数と短い光線長で済む典型的な接触影とは異なり、スクリーントレースはピクセル精度でなければならず、さもなければ遮蔽物をスキップしてしまう可能性があります。また、光線長はワールド空間で定義されるため、場合によっては画面全体をトレースする必要があり、固定ステップでは計算コストが高すぎます。
HZBトレースに依存することで、光線上の全てのピクセルをテストすることなく、素早く正確に空虚な空間をスキップすることが可能となる。
可能な限り典型的な画面空間アーティファクトを回避したいと考えています:
・したがって、デフォルトでは非常に保守的な低い表面厚さを仮定します。つまり、ほとんどの場合、光線が表面の背後を通過する際に交差があったと仮定するのではなく、ハードウェアレイトレーシングにフォールバックします。
・もう一つの問題は、長いスクリーントレースが深度バッファのエイリアシングにより顕著なアーティファクトを引き起こす可能性があることです。そのため実際には、これらの問題を回避するために長さを制限しています。
・深度バッファに対するトレーシングは、それ自体が自己影の問題を引き起こす可能性もある。これを回避するため、ポイントサンプリングとバイリニアサンプリングの両方の深度を組み合わせる。
また、ステンシルビットを用いてレイトレーシングでインスタンスが表現されているか追跡し、レイがそれらのピクセルのいずれかの背後に到達した場合、推定厚みを増加させてそれらのインスタンスからより多くの接触影を得るようにしています。

GIや反射については、アルファマスクに基づくBVH構築時に三角形を縮小・カリングするといった手法で、安価にオクルージョンを近似できる場合が多い。しかし、ダイレクトシャドウに対してはこれらの手法は効果的ではない。
理想的には、インラインレイトレーシング使用時に直接評価可能な「固定関数」アルファマスキングをサポートしたいところですが、アーティストがマテリアルグラフでアルファマスクを定義できるため、これは現実的ではありません。したがって、以下の選択肢が残されています:
・完全なヒット判定を用いた全光線の追跡が可能であり、正確な結果が得られます。しかし一方で、インライン光線追跡の恩恵を受けられないため、コンソールでは大きなオーバーヘッドが発生します。
・第二のアプローチは、まず通常の軽量なインラインレイトレーシングを実行し、マテリアル評価が必要なインスタンスに遭遇した場合にのみ、ヒット評価を有効にした「継続」レイを追跡するものです。この手法により、必要な箇所で精度を確保しつつ、全てのレイに対してインラインレイトレーシングの利点を損なうことはありません。
現行世代のハードウェアでは、ハードウェアレイトレーシングの使用が単純に非現実的な状況やコンテンツが依然として存在する:
・AHSの実行オーバーヘッドは、特に重なり合う三角形が多い密な葉の表現に通常使用されることを考慮すると、単純に高すぎる可能性がある。
・あるいは、BVH構築に大量のメモリと時間を要する、インスタンス化が高度に施されたアニメーションメッシュが存在する場合もある。
この問題を回避するため、特定のライトに対してハードウェアレイトレーシングを使用する代わりに、仮想シャドウマップへのフォールバックもサポートしています。
仮想シャドウマップは、我々の目的に有用な機能をサポートしています:
・それらは説得力のあるソフトシャドウを生成できるため、他の光源からのレイトレーシングシャドウと良好に調和する。
・ライトサンプリングパス中に、どのページがサンプリング対象かをマークすることで、シャドウマップへのメッシュ描画という不要な作業を回避できます。
このフォールバック手法は二者択一である必要はありません。アーティストは、どのインスタンスをシャドウマップにレンダリングすべきかを手動でタグ付けでき、レイトレーシングで十分に表現されているインスタンスについてはHWRTに依存できます。
ただし、このフォールバックオプションではシャドウマップのスケーリング問題は解決されない点に注意が必要です。BVHのコストは一度だけ発生しますが(いずれにせよLumenには必須です)、ライトごとのオーバーヘッドはほぼ存在しません。VSMの場合は事情が異なり、各ライトごとにシャドウマップを準備するための追加オーバーヘッドが発生します。複雑なキャッシュ機構を備えたVSM方式であっても、このオーバーヘッドは急速に累積し、手法全体を合理的な60Hzの予算範囲外に押し出してしまいます。そのため実際には、表現の不一致が目立ちやすく、BVHをシーンビュー範囲全体に拡張するコストが非常に高くなる方向性光源にのみ使用されます。

この図にすべてをまとめると:
・トレースパイプラインの中核はスクリーントレースで構成され、誤った自己遮蔽を避けるため常に最初にトレースされます。その後、近距離トレースが続行され、ほとんどの光線を処理します。
・レイがアルファマスク付きマテリアルを使用するオブジェクトに当たった場合、マテリアル評価を伴うレイの再トレースを行うオプションがあります。
・同様に、光線が近距離場半径を超えて伸びている場合、そのレベルに対する遠距離場表現に対して逆方向に辿り直すことができる。
・最後に、VSMを使用するライトについては、シャドウマップもサンプリングします。
各ステップ間でも一貫性を維持するため圧縮処理を実行します。この圧縮ステップでは一貫性を最大化するため、グループごとに16×16のトレースタイルを処理します。

ほとんどのゲームでは実際には数千ものライトが出力されないため、UEのような成熟したエンジンであっても、大量のライトを処理し始めると、まだかなりのパフォーマンス向上の余地が残されていました。例えば、ライト数のヒートマップ可視化機能はデフォルトで最大閾値を8ライトに設定されており、これは実装当時の要件を示しています。
アーティストも複雑なライトタイプ(rectライトやテクスチャ付きライトなど)を頻繁に使用し始めるため、エンジン全体でそれらを効率的に処理できるようにする必要があります。

ライトグリッドの実装は、数千個のライトにスケールアップする際に負荷を感じ始めたため、大量のライトを適切に処理できるようビルドロジックの改善が必要となった。
更新された実装は以下の通りであり、MegaLightsデモにおけるグリッド構築時間を0.6ms超から0.2ms未満に短縮しました。この10年間でこのテーマに関する多くの研究と論文が発表され、非常に効率的な手法が提案されているため、さらなる最適化が可能と考えられます。
既存のフロクセルベースの構造は維持しましたが、ライトの挿入を2段階に分割しました。まず、単一スレッドですべてのライトをループ処理するのは非常に遅いため、セルごとに1つのスレッドグループを使用してライトを粗いグリッドにカリングします。次に、この粗いグリッドの結果を用いて、レンダリング時に使用するメイングリッドへのライトのカリングを行います。この2回目のパスでは、セルごとにチェックが必要なライト数が大幅に減少するため、通常はセルごとに1スレッドで十分です。セルごとにフルスレッドグループを使用するとリソースが無駄になる可能性があるため、ライト数に基づいてセル処理に1スレッドか1スレッドグループを使用するかを動的に決定できます。32レーン対応のプラットフォームでは、Wavesが適切な中間グループを提供します。
各セルのライトリストを圧縮する必要がある。最悪ケースに備えてグリッドセルごとにメモリを割り当てると、大量のメモリが無駄になるためだ。これには、セルごとの関連ライト数をカウントし、バッファ内に領域を確保し、リストのインデックスを書き込む処理が必要となる。グローバルリストを2回ループする必要(カウント用と書き込み用)を避けるため、まず関連するライトリストをLDSに書き込み(グローバルメモリの共有バッファに格納されたリンクリストへ溢れ出し)、実際のグリッドバッファに領域を確保し、その後LDS+溢れ出しリンクリストからそのバッファへリストをコピーします。
多くの場合、光グリッドセルの大部分は遮蔽されており、HZBカリングにより光グリッド構築のオーバーヘッドを大幅に削減できます。フロクセルグリッドの非線形性により、セルサイズは深度とともに増加するため、遠方のセルは多くの光の影響を受けるため通常よりコストが高く、スレッドがすべての光インデックスを書き込む際に帯域幅に制限される可能性があります。

カリング境界を厳密に設定することは、パフォーマンスを最大化するために極めて重要です。ライトグリッド構築と同様に、この分野では様々な側面を扱う多くの論文が発表されるなど、広範な研究が行われてきました。しかし、カリングの観点で見落とされがちなライトの一種が矩形ライトです(おそらくこれまでゲームでの使用例が少なかったためでしょう)。バーンドアを考慮に入れてカリングを厳密化することで、矩形ライトが影響を与えるセル数を大幅に削減できることを我々は発見しました。

シェーダーでは、多数のマテリアルタイプと光の特徴を処理する必要があるため、レジスタの負荷と占有率も考慮すべき要素です。
この課題に対処するため、材質タイプと各タイルに影響を与える光の種類を基にタイル分類を実行し、必要な箇所で最悪ケースのVGPR使用量のみを負担するようにしています。
特に、直線光とテクスチャ付き光をサポートするロジックはかなりのオーバーヘッドを生むため、これらには専用のシェーダー構成を用意している。MegaLightsデモでは、光グリッド構築時に各セルに影響する光の種類を追跡することで、光の種類に基づくこの追加分類を実施した結果、オーバーヘッドをほとんど増やさずに占有率を約20%向上させた。
これで不透明パイプラインの説明は終わりです。次は半透明と体積フォグに移りましょう。

UEでは、ボリュームメトリックの照明を2つの構造で計算・保存します:
・ボリュームフォグには、カメラに整合したフロクセルグリッドを使用します。
・粒子エフェクトについては、カメラ周囲にワールド空間グリッドを設置し、各ボクセルごとに2バンドの球面調和関数を格納しています。
これらの構造体は毎フレーム、内部に光を注入することで更新され、影の計算は通常シャドウマップを用いて行われます。しかし、主にレイトレーシングによる影に依存する場合、シャドウマップが存在せず、多数の光を注入することも非常にコストがかかります。そのため、これらの構造体は新システムと統合されるよう改良されました。

不透明ピクセルに用いられる一般的な手法は、ボリュームに対しても同様に適用できる:
・サンプリングを半解像度で実行し、ボクセルごとにN個の光サンプルを選択できる
・シャドウレイをトレースする
・可視サンプルの照明評価には、ボリュームフォグの位相関数と半透明ボリュームの拡散BRDFを使用する
・最後に、次のフレーム用の可視光リストを作成します
そしてこれを2回行わなければなりません。各巻ごとに1回ずつです。

しかし、この単純明快なアプローチにはいくつかの問題点がある:
・まず第一に、プローブは非常に疎であり、特にワールド空間グリッドでは、近傍ボクセルからの可視性収集は、高頻度シャドーイング領域において非効率的なガイディングを引き起こす。
・第二に、2つのボリューム間で重複作業が多数発生しています
○ 重要なライトを選択し、ワールド内の多数のプローブから影レイをトレースしています
○ しかしこれらのスクリーンショットでわかるように、これら2つのボリュームのプローブのカバー範囲は大きく重複しています。

一つの案は、フロクセルのグリッド構造を拡張してSHも保存し、それを使ってパーティクルエフェクトや半透明オブジェクトの照明を計算することです。これは2つのボリューム間で作業が重複するのを避け、フロクセルの方が密度が高いため半透明のガイド効果を向上させる効率的な方法のように思えます。しかし実際には、これによりいくつかの目立つ視覚的なアーティファクトが発生します:
・まず第一に、フロクセルグリッドの基盤構造が非常に目立ちます。特にカメラが移動する際に顕著です。
○ この種の問題はワールド空間グリッドでも発生しますが、少なくともカメラ依存ではないため安定しており、それほど気になりません。
・時間フィルタリングも必要ですが、再投影により完全に回避できない顕著な誤差が生じます。

別の選択肢として、サンプリングとトレーシングのみを2つのボリューム間で共有するハイブリッドソリューションがあります。
フロクセル位置に基づくプローブに対してサンプリングロジックを実行します。フロクセルは密度が高いため、ガイディング効果を損なうことなく隣接プローブ間で可視性データを共有できます。
その後、それらのサンプルに対して光線をトレースし、最後に各ボリュームごとに1つずつ、合計2つのシェーディングパスを実行します。各ボリュームは、最も近いサンプリングプローブから確率的にサンプルを収集します。
この手法では、サンプリングとトレースを2回実行する必要がないため、ボリューム構築にかかる時間を約25%削減できます。

不透明パイプラインについて述べた際、通常エネルギーの80%が単一の光源から来ると仮定すると説明しました。
不透明表面の場合、サンプリング時のシェーディングに法線とマテリアルプロパティを利用できるため、ピクセルあたりのサンプル数を少なく抑えられます。一方、半透明ボリュームのサンプル選択はより困難です。
まず、光を球面調和関数に注入しており、各ボクセルがどの表面をシェーディングするかは事前にわからない。
フロクセルはピクセルサイズに比べてかなり大きいため、隣接ボクセルからの確率的アップサンプリングは不安定性を招くか、より広いフィルタリングを必要とする。
サンプリングは統一された体積内で行われるため、位相関数と半透明BRDFの両方を考慮する必要があり、これにより光の重み付けがより均一になります。
これらの要因が組み合わさることで、不透明な表面に通常必要とされるよりも多くのサンプルを1ボクセルあたりにシェーディングしなければならない結果となります。

これを行う簡単な方法の一つは、ボクセルあたりのサンプル数を増やすことですが、これによりパイプラインの全段階の計算コストが増大します。
あるいは、シェーディング時に既に実施している確率的アップサンプリングを拡張する方法もある。単一の近傍からのサンプルをシェーディングする代わりに、複数の近傍からサンプルを収集してシェーディングするのだ。これにより追加のサンプリングやトレースのオーバーヘッドは回避できるが、可視性項がぼやける結果となるため、照明の詳細が多少失われる。
最後に、ボリューム内の安定性をさらに向上させるため、時間的および空間的なフィルタリングも適用します。

ガラスのような半透明素材には、鏡面反射を含む高品質な照明が必要です。
単純なアプローチとしては、最前面レイヤーを最も重要とみなして、正確な照明を得るためにMegaLightsパイプライン全体を再度実行してシェーディングする方法がある。しかし実際には、プレイヤーがそれらの表面に近づいた場合、照明コスト全体が容易に倍増してしまうため、通常はコストがかかりすぎる。
しかし、複数のレイヤーのシェーディングもサポートする必要があるため、よりスケーラブルな方法でこれを処理する必要があります。安価な選択肢の一つは、これらの表面を透過体積を用いて照らすことです。既存の球面調和関数を利用し、主方向を抽出して鏡面反射光を近似できます。単純なケースでは有効ですが、スクリーンショットでわかるように、鏡面ハイライトは1つしかサポートできず、SH内での照明が安定している必要があります。さもなければ、照明が静止していても鏡面反射が顕著に揺らぐことがあります。
現時点ではこの手法を採用していますが、この種の半透明表面における照明品質の向上を図るため、継続的な改善を進めている領域です。

透過処理も対応していますが、現時点では薄い表面のみに限定されており、これにより葉の照明効果が大幅に向上します。
伝送にはメッシュの裏側からトレースする必要がある場合があり、その際はいくつかの調整が必要です。スクリーンスペーストレースは無効化します。これはジオメトリの裏側をトレースできないためです。またバイアス設定を変更し、光の方向へわずかに偏向させる必要があります。これにより、光線は植生ジオメトリと即座に自己交差する代わりに、その裏側を迂回できるようになります。
葉の裏側から光線が当たる点までの距離は距離推定値となり、これを伝播項に代入できる。

それでは、実行時のパフォーマンスという観点で、これらすべてがどのように組み合わさるのかを見ていきましょう。
これらの数値は、PlayStation 5上で1080pのレンダリング解像度、1ピクセルあたり1サンプル、非同期演算を無効化した状態で動作するMegaLightsデモからのものです。
画面上に900個以上のライトが存在し、その結果、1ピクセルあたり約20~80個のライトが処理されています。
総コストは約5.5msで、直接照明のすべてのシャドーイングおよびシェーディングコストをカバーしています。

注目すべき点として、不透明サーフェスのサンプリングは、解像度が半分であるにもかかわらず、シェーディングよりも時間がかかる。
これはサンプリングコストが光源数に比例するためであり、このシーンでは光源数が非常に多い。さらにそれらの光源の多くが矩形ライトであり、サンプリングコストが高く占有率を低下させるためである。
一方、シェーディングはピクセルあたりにシェーディングされるサンプル数に上限があるため、より固定的なコストを持つ。コストはタイルタイプのみに影響されるため、比較的安定している。

もう一つ注目すべき点は、半透明シェーディングは画面上のピクセル数に比べてプローブ数が大幅に少ないにもかかわらず、不透明シェーディングとほぼ同等の計算コストがかかることです。
それは、先ほど議論したように、半透明表現では安定性を向上させノイズを低減するために、1ボクセルあたりより多くのサンプルをシェーディングする必要があるためです。

全体的に、アーティストがMegaLightsを使い始めると、彼らがどれほど楽しんでいるかがすぐに明らかになります。
メガライツのデモ制作中に彼らが新たな考え方に移行していく過程を見るのは非常に興味深かった。最初はゆっくりと、あちこちにライトを配置する程度だったが、それはすぐに変わり、レベル内に多くのライトが配置されるようになった。

このスクリーンショットでわかるように、矩形ライトの使用も増加し始めました。

アーティストが光を形作るためにメッシュを使用しているコンテンツを数多く発見し始めました。これにより、それらの光を正しくサンプリングし、解像することが非常に困難になっています。
理想的には、ライトは光関数(サンプリングパス中に安価に評価可能)を用いて形状化され、各ライトごとに指定された光線終端バイアスを用いてフィクスチャの幾何形状をスキップすべきである。
実際のところ、それほど大きな問題ではなかったので、デモ版はそれらのメッシュベースのフィクスチャをそのまま搭載してリリースしました。ただ、遠方のオブジェクトが自動カリングされて光漏れが発生し、全体の照明が大幅に変化するのを防ぐため、アーティストにBVHファイル内で手動でタグ付けするよう依頼する必要がありました。

ある時点で、アーティストたちはプロシージャルなライトスポナーといったツールを使い、スプラインに沿って自動的にライトを配置することに非常に慣れ親しむようになった。

システム全体のスケーラビリティが大幅に向上し、許容範囲も広がりました。その結果、壁の内部にランダムなテクスチャが適用されたエリアライトが存在したり、IESプロファイルを持つ単一のライトを使用せず、複数の光源で構成されたライトが使用されていたりするケースが頻繁に発見されるほどです。
それでも確率的光サンプリングは万能薬ではなく、光源はサンプリングパスの性能を低下させるか、シーン内のノイズを増加させる。減衰範囲の縮小、コーン角の縮小、バーンドアの使用といったコンテンツ最適化が重要となる。
レイトレーシングは、コンソールのようなリソース制約の厳しいプラットフォームにおいても、直接照明の解決に向けた新たなアプローチを可能にします。
もちろん、次のような品質上の制限は依然として存在します:
・レイトレーシングにおけるメッシュの表現精度
・そしてほとんどの場合、1ピクセルあたり1サンプルに制限されるため、慎重なサンプリングとノイズ除去が極めて重要である。
この手法の性能は、ピクセルあたりにサンプリングされるライトの数とレイトレーシングシーンの複雑さに比例して向上する。
ここには恐ろしい制限があり、明らかにライトのカウント数も依然として制限されていますが、全体としては実践的にはかなり良いトレードオフとなりました。アーティストはシステムが破綻する前に、はるかに自由にライトを配置できます。さらに、確率的アプローチはパフォーマンスと品質の間を自由に調整できる点に優れており、これにより、手間のかかる手動でのライト調整に頼ったり、異なるスケーラビリティレベル向けに複数のライト設定を維持したりすることなく、より柔軟性を得られます。
BVHの制限は恐ろしいものですが、実際にはアーティストはエリアライトを配置することを好みます。これらは通常、接触点付近にのみ詳細な影を投射するオブジェクトを必要とします。この光線の最初の区間はスクリーンスペーストレースで十分に処理できるため、ローカルライトには妥当な解決策となります。指向性ライトは課題となる場合がある。遠距離描画時にシャープな影を要求する可能性があり、BVHでは非現実的だからだ。その場合はVSMにフォールバックできる。VSMのみに依存する方法、あるいはレイトレーシングとVSMトレーシングを組み合わせたハイブリッド手法を採用する方法がある。
高速移動時には時間的アーティファクトが発生する可能性がある。これは、全ての確率的光サンプリング手法が複数フレームにわたるデータの蓄積と再利用に依存しているためである。光源数が少なく光源サイズが小さい場合には顕著な問題とはならない。通常、ピクセルごとに最も重要な光源を1つサンプリングするだけでほぼ瞬時の応答が得られるからだ。しかし光源が大きい場合や、ピクセルあたり重要な光が多くなる場合、状況は多少悪化します。複数フレーム分のデータに依存する必要が生じるのに、そのデータが存在しないためです。とはいえ実際のゲーム開発では概ね良好に機能しており、時間的アーティファクトは通常ノイズ除去処理で隠蔽されます。また高性能GPUではピクセルあたりより多くの光線追跡が可能となるため、これらの問題はより軽微になります。

今後の作業としては、MegaLightsの製品化に向けた準備を進めています。最適化や修正、実装が必要な機能など、まだ改善すべき点が多く残っています。
例えば、BRDFサンプリングと明示的サンプリングを組み合わせたいと考えています。明示的サンプリングは、小さかったり表面から遠く離れた光源のサンプリングに最適です。BRDFサンプリングは、大きな光源や反射型BRDFに最適です。既にBRDF光線(ルーメントレース)を用意しているので、それらを低コストで再利用することで直接照明の品質を向上させられます。
GPU駆動のフィードバック機構を活用し、レンダリングされたフォワードシェーディング表面に基づくサンプル誘導を実現することで、フォワードシェーディングのサポート強化に取り組んでいます。また、この技術を実運用で活用しているライセンシーからのフィードバックを収集しており、これによりMegaLightsのデバッグと最適化に役立つツールの準備が可能となります。
ローエンド(モバイル)へのスケーラビリティは依然として未解決の問題である。一部のゲームタイトルでは、安価な携帯電話からハイエンドPCのGPUまで、非常に幅広いハードウェアでコンテンツを動作させる必要がある。MegaLightsを使用してコンテンツを作成すると、ライティングアーティストに多大な作業を強いることなくライト数を削減することが困難になる。アーティストが複数のライティング設定を手動で維持しなければならない状況に陥ることは避けたい。
もう一つの重要な領域はノイズ除去とアップサンプリングです。現在MegaLightsは独自のノイズ除去を実行し、その出力がさらにTSRによって処理されるため、様々な課題が生じています。これら2つのプロセスをより統合的にする方法を検討したいと考えています。内部ノイズ除去器から追加情報を渡す方法、あるいは全てのノイズ除去処理をTSRに移行する方法のいずれかです。この分野では機械学習を用いた非常に有望な結果を示す新たな研究が数多く存在しています。
将来の主な課題は、ハードウェアレイトレーシングにおけるメッシュ表現である。
これまで拡散GIやラフ反射は比較的許容範囲が広いため、低ポリプロキシやその他の近道で(ある程度)ごまかすことができてきた。しかし直接照明の影は、メッシュのレイトレーシング表現を容易に露呈させてしまう。
動的ジオメトリは依然として未解決の問題であり、メモリとパフォーマンスの予算を容易に超過するため、現時点では多数のアニメーションインスタンスを正確に表現することは不可能である。
大量のキットバッシュや内部に空虚な領域が多い巨大なメッシュ(例:単一メッシュからモデリングされたスカイボックスメッシュや洞窟)は、ハイエンドPCのGPUであってもレイトレーシングのパフォーマンス問題を引き起こす可能性があります。理論上はBVH再編で対処可能だが、再編はかなりコストの高い操作であり、さらに多くのメモリを必要とする。これは既にBVH構築時間が課題であり、BVH表現自体に大きなメモリオーバーヘッドがあるため、理想的とは言えない。
Nanite(当社の仮想化ジオメトリパイプライン)により、ラスタライゼーションにおけるメッシュ最適化の問題の大半を隠蔽できましたが、レイトレーシングの制約によりそれらの問題が再浮上し、アーティストはBVH表現を慎重に最適化する必要があります。
レイトレーシングAPIの新たな拡張により、Naniteメッシュの効率的な表現が可能になりつつある一方で、ジオメトリの複雑さは絶えず増大しています。
レイトレーシングでの表現がさらに困難な新たな種類のコンテンツが存在し、純粋なレイトレーシングによる影表現を実現するには、まずこれらの課題に対処する必要があります。


































