UE5 Lumen実装分析

##概要

LumenはUE5のGIシステムで、間接拡散反射の寄与のみを含む従来のリアルタイムGIとは異なり、間接拡散反射と間接ハイライトも含まれ、真新しい間接照明セットを提供します。Lumenは、ハードウェアベースのRTXとソフトウェアベースのTraceという二つのアルゴリズムをサポートしています。本記事は、Lumen GIがソフトウェアベースのTraceの間接拡散反射のプロセス、アルゴリズム、およびデータ構造分析から出発して、マクロの観点からLumenの基本原則と実行メカニズムを理解したいのです。
Lumenの中心となる内容は、次の部分です。
>１、ユニークな簡略されたシーンの表現です。Lumen には、GI反射を提供するシーンはモデルで構成されではなく、これらのモデルの簡略化されたプロキシMeshCardで構成されています。
>２、ディスタンス フィールドの交差加速度に基づいて、LumenのソフトウェアTraceで使用されるコア加速度構造はGlobalDistanceFieldとMeshDistanceFieldです。イルミネーションの表示はシーン構造から分離されていて、Lumenで照明情報をキャッシュするコアコンポーネントは2つあります：1つは最高精度の照明を格納するAtlasTextureで、各SubTextureはMeshCardに対応し、シーンエンティティモデルの一部のクリップにも対応します。もう1つのコンポーネントはVoxelです。これは実行時に生成され、Lumenの光情報表現の最も主要な部分です。
>３、Screen Space ProbeによってGIを解きます。そのプロセスはSSGI、MeshDistanceField Traceに基づいたMeshCardAtlas Textureの照明の解析・計算、GlobalDistanceField TraceのVoxelに基づいた照明の解析・計算など多くのGIアルゴリズムによって統合されます。

---

##データ構造 

###一、交差加速構造

Lumenには、3D空間のDistance FieldとHZBの2つの主要なTracing交差加速構造があります。ディスタンス フィールドは、Mesh Distance Field（以下、MDF）とGlobal Distance Field（以下、GDF）に分けられます。MDF / GDFは、3D空間でのモデル（MeshCard / Voxel）の交差を加速するために使用され、Hierarchy Z Buffer（以下、HZB）は、スクリーンスペースでのSSGIのRayCastの交差に使用されます。
###二、MDF / GDF

BVHがない場合、RayTracingは固定ステップを使用して、光の方向に沿って均一にステップし、且つ各ステップの後にシーンを交差します。薄いメッシュや小さなモデルをエラーなしで貫通するには、ステッピングサイズを無限に小さくする必要があります。実行効率を上げるには、ステッピングサイズをできるだけ長くすることが望まれます。2つの要件は完全に反対です。均一ステップの図は次のとおりです。


MDF / GDFが出現した後、モデル表面に最も近い位置を格納するため、この状況を効果的に変わりました。つまり、多くの場合に、ステップのサイズは大幅に長くされたけれども、「モデル」貫通のエラーは生じません。下図のように、カメラの正面から光が放射すると、青い円は、現在の点に保存されているDistance Field（オブジェクトまでの最短距離）です。この距離内（円の内）に他のオブジェクトは存在する可能性がないため、毎回のステッピングの長さはDistance Fieldの距離に相当します：


###三、HZB

スクリーンスペースでのRayMatchと3D空間でのRayTracingには、全く類似したステッピングの問題があります。スクリーンスペースには完全な3Dシーン情報が欠けているため、RayMatchのヒット判定は、現在のピクセルの深度Zと光線方程式のZ値のサイズを比較することによって近似されます。――現在のピクセル光線の深度はZBufferの深度以上である場合、（以下の説明は一般的なZBufferに基づいており、Reversed Zなら、規則は相反する）、既に交差しているとなりますが、そうでなければ、オクルージョンがないと思われ、ステッピングを続行できます。HZBの基本的な考え方はBVHに似ています。最初に、現在のZBufferの為にMipmapを生成します。ここで、高いレベルのMip Z値は、前のMipにある4ピクセルの最小値を取り、RayMatchを実行時にそのうちのあるレベルのMipから始めます。現在のMipに交差がない場合は、Mipレベルを上げて交差を続けます。それ以外の場合は、Mipを減らしてより細かい粒度で交差させます。その意味は、最初に大きいピクセルBlockで、RayMatchingがの現在のBlockと交差するかどうかを確認することです。交差が小さいピクセルBlockで見つかり、交差がずっとあったら、必要な最高の精度というレベルに下げ、光が現在のピクセルと交差するかどうかを照会します：逆だったら、より大きなBlockに交差点があるかどうかを確認します。それなら、かなり大きなピクセルごとにStepする領域をすばやくスキップできます。二つのレベルでのRayMatchの見取り図は次のように示します。


###四、MeshCardとLumenScene

LumenSceneは、計算プロセスでLumenが使用するシーンで、リアルなシーンの不完全てきな簡略化されたバージョンです。Traceベースのアルゴリズムの場合、簡略化されたシーン表示を選択するには、Traceを高速化させると同時に、Traceの精度の低下にも引き起こします。MeshCardはLumenSceneの基本コンポーネントであり、シーン構造から見ればもLumenSceneの基本要素です。LumenSceneにとって、シーンにモデルは存在しません——MeshCardがその代替（Proxy）です。
リアルタイムGIでのより一般的な簡略化されたモデルは、ボクセル（Voxel）と表面要素（Surfel）です。LumenのMeshCardは幅と高さが等しくなく、且つ1つの座標軸のみがOrientation∈[-x、+ x、-y、 + y、-z、+ z]ある六面体です。形状から見れば、それはブロック型の積木です。
LumenSceneは、このような積木で1つずつ構築されますが、手動で構築する必要はなく、自動的に生成されます。LumenのMeshCardの主な機能は、光のサンプリングの位置と方向を提供することです。これは、光情報の実際の構成要素と基本的な構成要素を同時に大幅に削減するために使用されます。MeshCardの6つのOrientationは、即ちAmbient Cube1 の6つの基底関数です。モデルの同じ位置にあっても、6つまでのMeshCardが存在する可能性があり、各MeshCardは異なる方向を表します。この表示式は、DiffuseLightingに対してより高い忠実度を持つことができ、Probe BasedのさまざまなリアルタイムおよびベイクGIソリューションで広く使用されています。同時に、データを復元する際の命令量がSHより合理化されています。


###五、Screen Space Probe

Lumenは、現在のフレームの画面ピクセルに対応するワールド位置を使用してProbeを配置することで、ScreenSpace Probeと名付けました。
ProbeのRadianceは2つの表現方法があります。1つは八面体マップ（OctahedralMap）[6]ストレージ、デフォルトサイズは8 * 8、もう1つは球面調和関数で、Probeの計算が完了した後に生成されます。八面体マッピングでは、2D のRenderTargetをAtlas Textureとして使用してすべてのProbeを格納し、楕円マッピングで処理するのが難しい境界シームの問題はありません。次の図に、2Dテクスチャから球および半球への八面体マッピングのマッピングプロセスを示します。より詳しいアルゴリズム6を参照してください。


Meshcard Atlas / Voxelがあってから、Lumenは再びScreenSpaceProbeに参入して、中間光ストレージとして格納します。それは沢山のメリットがあります。
非常に低い解像度のSpaceSpaceProbeを使用すると、最終GI解析・計算プロセスを大幅にスピードアップさせます。
異なる信号周波数（Meshcard Lighting / VoxelLighing / SSGI）の照明情報をスムーズに組み合わせ、八面体マッピングと低次SHはすべて低周波数IrradianceMapの表示方で、異なる周波数の信号をScreenSpaceProbeに投影することはこれらの光源をローパスフィルタリングすることと同様です。
ProbeはCacheや再利用できます。Screen Space Probeの巧みなところは、スクリーンスペースで生成されますが、完全なRadianceセマンティクスを保っています。各Probeは実際に特定のワールドスペース位置に存在するため、カメラは緩く移動する場合、各フレームのスクリーンに表示されるProbeのごく一部のみが変更されるため、Cache Probeの可能性が生じます。
RTXのような重いFilterで分散を抑制する必要はありません。
##Lumenの基本的なプロセス

Lumenのプロセスは、オフラインデータの生成、実行時データの更新と照明計算、2つのモジュールに分かれています。2つのモジュールの主なタスクは次のとおりです。


*オフライン段階*

オフラインで生成されるデータには、MeshCard、MDF、およびGDFが含まれます。これらは、静的モデルのインポートまたは変更後に自動的かつ非同期に生成されるため、Build手順を実行する必要はありません。 MDFとGDFの2つ部分のデータが同時にあるのは、MDFの精度がGDFの精度よりも高いからです。実行時に、MeshCardはシーンコンポーネントとライトのキャッシュ構造の両方として使用されます。
 
*実行段階*

Lumenには、最終的なGI計算を完了するために、実行時に4つの主要なタスクがあります。
>[1] LumenSceneを更新します
>[2]直接および間接のDiffuseライトをライトキャッシュに注入します（MeshCards と3D Clipmapに基づいたVoxelなどを含む）
>[3]現在のスクリーンスペースに基づいてProbe及びTraceで得たProbeのライト情報を自動的に配置して、Probeのライト情報に対して2次エンコードを実行して、IrradnianceCaheを生成します。
>[4] Probeのライト情報、2次エンコードされたライト情報、およびIrradiance Cache情報を使用して、最終的なIndirect DiffuseとIndirect Reflectionを計算し、Historyのライト情報と混合して最終的なGIエクスポートを作ります。
以下は、これらの段階での要点への紹介と分析です。

###一、LumenSceneを更新する

####１、Primitiveに基づくデータの更新

LumenSceneのデータは2つの部分に分かれており、1つはFSceneの静的モデル（MeshCard、2種類のDFデータを含む）から直接取得され、もう1つはMeshCardとDFデータを使用して生成され、レンダリングに用いるライトキャッシュデータから取得されます（エンコード後の各種類のAtlasテクスチャを含む）。したがって、LumenSceneの更新ドライバーにも2つの部分があります。1つはシーン内のデータの変更で、もう1つは、後続のライト計算のためにフレームごとに更新する必要がある特定のライトキャッシュのデータです。これらのデータ更新は、マルチスレッドで実行されます。
LumenSceneのPrimitiveデータの更新操作は以下の通りです。
>新しいPrimitiveがシーンに追加され、ISMなどの複数のInstanceがLumenCardマージを行い->新しいMeshCards・DFがLumenSceneに追加されます。
既存Primitiveはシーンから削除され->Dirty MeshCards・DFがLumenSceneから削除される
>Primitiveには更新がある-> MeshCards、DF のTransform / Lodなどのデータを更新する。
>マテリアルやライト情報など、AtlasTextureの MeshCards位置とサイズを割り当てて更新する。
>近くにまだキャプチャされていないマテリアルパラメータのMeshCardsをレンダリングのリストに追加します。（デフォルトの近くというのは、カメラから200メートル以内のすべてのMeshCardsを指します。また、MeshCardsのバウンディングボックスは、指定された閾値よりも大きい必要があります。さらに、各フレームにレンダリングされるMeshCardsが指定された数を超えないように制限します。ここでフレーム分割処理が実行されます）。
>Cacheの近くのMeshCardsは、静的モデルのレンダリングコマンド（DrawCommands）とNaniteのレンダリングリストに対応し、マテリアル属性（MateialAttributes）をキャプチャするために使用されます。静的モデルは最大のLodレベルを使用することで、マテリアルキャプチャのコストを節約します。
LumenSceneは、シーンを遠景と近景2つの部分に分割します。したがって、Primitive以外、シーン内のカメラの動きによってLumenSceneの更新もトリガーされます。
>遠景の生成に使用されるMeshcards（デフォルトでは、Cascadeという1つのレベルしかありません。つまり、Meshcardsを使用するだけで遠景を表現します。）
さらに、Naniteモデルについて：
>NaniteのマルチInstanceは、LumenSceneに参加するときに自動的にマージ操作を実行することで、MeshCardsの総数を減らします。
*MeshcardsとAtlasTextureに関する注記：*
AtlasTextureの編成では、Bin Packingアルゴリズムを使用して編成します。新しいMeshcardsはそれぞれAtlasTextureに割り当てようとします。ここでは、UE4の既存のTextureLayoutコンポーネントがサブテクスチャの割り当てに直接使用されます。
>AtlasTextureでのMeshCardsのSubTexture Sizeは、MeshCard自体のサイズと、MeshCardと現在のカメラの間の距離によって決定されるため、カメラが移動したときにAtlasTextureの再編成もトリガーされます。
> MeshCardsに対応するSub Textureの面積は一般的に1テクセルよりも大きい
>各フレームは一定的なMeshCards数を更新するため、優先順位でNew MeshCardsが最初に作成されることを保証し、その後Update MeshCardsの更新要求を処理するようにします。

####２、MeshCardsのマテリアル属性をキャプチャする（MaterialAttributes）

MeshCardのストレージ構造からわかるように、自分のマテリアル属性や深度の情報が保存されていません。これはおそらくディスクスペースを節約し、その精度の適応可制御性を確保するからかもしれません。オフラインベイクで欠落しているデータは、実行中に生成させ、後で使用するために対応するAtlasTextureに保存される必要があります。次のステップは、MeshCardsのために、GIのマテリアルおよびその他の幾何形体を計算するためのデータを用意することです。これらのデータ属性には主に次のものが含まれます。
>Material Albdo、Diffuse Lightingの計算をサッポートする。
>Material Emissive、自己照明のシーンをサッポートする。
>Material Opacity，光の透過及び半透過のオブジェクトでの半分バウンスを処理する
>Normal、ライトモデルに用いられ、各種類のライトを計算する。
>DepthStencil、Probeを放置する点を計算するとか、ライト補間の重みを計算するとか、Lumen後の各段階にも応用される。
ステップ1で、Meshのレンダリングリストが既に処理されました。パフォーマンスを節約するために、先ずはInstanceを編成します。NaniteのCull-Drawプロセスと従来の静的モデルとは完全に異なるプロセスなので、ここでのプロセスも2回実行する必要があります。また、MeshCardsはGIの計算に使用されるため、視野内にあるかどうかに関係なくレンダリングに送信するべきです。そのゆえ、Cullプロセスはここで無効になります。
マテリアル属性のキャプチャ操作が完了すると、次の操作が実行されます。
>Depthのモーメント(Moments)を計算し、Mipmapを生成します。これは、後続のTrace時にチェビシェフの不等式を使用してOcclusionを推定するために使用されます。この処理方法は、Variance Shadow Maps[3]から由来し、DDGI[4]にもIrradiance Volumeの可視性を処理します。
>Opacityを前処理し、Mipmapチェーンを生成します。

###二、キャッシュにライトを注入する（Inject Lighting To Cache）

MeshCardsデータの更新とマテリアル属性のキャプチャが完了したら、次のステップは、現在のシーンのライト情報をライトキャッシュに注入することです。 Lumenは、3つの主要なデータ構造で、シーン内のライト情報をキャッシュします。それぞれMeshCardsとそれに対応するAtlasTexture（最高精度）、Voxel 3D Clipmap [2]（中精度）、およびGI Volume（ボディレンダリングに用いる）です。 これらの3種類のデータは、シーン内の静的オブジェクト、動的オブジェクト、およびボディレンダリングのオブジェクトを同時にカバーでき、完全なGI光源を形成できます。
ライトを注入する全プロセスを次の図に示します。


####１、VoxelLighting

LumenのVoxelLightingはVXGIに似ており、3D Clipmapベースの方法を使用してストレージスペースを節約します。ただし、LumenのVoxelLightingのすべての3Dテクセルは、VXGIのVoxelと同じではありません。Lumenの各3Dテクスチャは、Ambient Cube [1]の特定の方向の光投影パラメータを表します。実際に必要な3Dテクセルの数はそのサイズの6倍です。VoxelLightingがMeshCardsとほぼ同じ構造（六面体）と基底関数（AmbientCube）を選択していることがわかります。Clipmapに関する詳しい紹介は、参考文献[2]および[5]にあります。
次の図は、サイズが4096の3Dテクスチャのフルmipとサイズが64 * 64の3D Clipmap両者において、ロードする必要のあるテクセルの数の対照を示しています。


VoxelLightingは、デフォルトで4レベルの3d Clipmapを使用し、カメラのワールド位置を中心に200メートルの範囲（配置可能）で間接ライト情報を保存します。すべてのMipLevelsとDirectionsは、3Dテクスチャでタイル張ります。
テクスチャサイズは[64、64 * MipLevels、64 * Directions（6）]です。X軸はClipmap Sizeと同等する以外、すべてのMipLevelはY軸に広がり、Ambient Cubeの6方向はZに広がります。
各レベルのMipの表される距離は指数関数的に増加します。レベル0の範囲は[0、25メートル]、レベル3の範囲は[100メートル、200メートル]です。逆に精度を計算すると、レベル0の精度は25メートル* 2/64で、各Voxelで表現されるシーンスペースは約0.78メートルで、類推してレベル3の精度3.125メートルを求めます。

####2.メッシュカードに光を注入する

上記のフローチャートから、MeshCardsのライト注入は、直接光と間接光の2つの部分に分けられ、直接光と間接光の両方が、&SpecularではなくDiffuseの寄与のみを計算することがわかります。
最初のステップは、MeshCardsの間接光を計算することです。間接光の計算は、光源データソースとTrace方式という2つの次元に応じて分割できます。Lumenは、以下の表に示すように、4つの異なる間接光計算モードをサポートします。


デフォルトでは、LumenはVoxelLightingを間接光の光源として使用し、ブロックTraceを再利用して、 MeshCardの間接ライトを計算します。さらに、間接光の光源とサンプリング方法には、注意すべき2点があります。
>間接光源の2つの光源であるVoxelLightingとIrrdianceCacheは、どちらも後続のLumenプロセスで生成されるため、ここでサンプリングされるデータは、前のフレーム又は以前の履歴データです。
>テクセルごとにサンプリングして生成される間接ライトは、精度は高くなりますが、より多くのサンプリング点が必要になり、パフォーマンスが低下します。ブロックベースのTrace  では、隣接するテクセルのサンプリング結果が再利用されるため、ほとんどの場合、より少ないサンプル数を使用してよりスムーズなサンプリング結果を達成できます。
間接光のVoxel Traceに対する説明：
>１、Global Distance Fieldを使用して加速して交差する
>２、Voxel ConeTraceを使用してVoxelLightingをサンプリングする。デフォルトでは、テクセルごとに8つのConeがサンプリングされます。Hit距離に応じて、どのレベルのMipmapを使用するかを決める。
>３、サンプリングされたConeは、スカイライトもサンプリングし（スカイライトがオンになっている場合）、それをLighting結果に重ね合わせます。
2番目のステップは、間接光の結果に対してBilinear Filterを再度実行し、<0の異常値をフィルタリングする。
3番目のステップは、直接光の寄与を計算することです。Lumenでサポートされている直接光のタイプには、PointLight、SpotLight、RectLight、DirectionalLightがあります。ランプごとに計算されるDirectionalLightを除いて、他の3つのタイプの照明はバッチで実行されます-照明範囲が限られているため、このバッチで影響を受けるMeshCardsのみを見つけることができます。毎バッチの直接光へのレンダリングは、影響範囲内のMeshCardsでのみ機能します。
直接光計算のもう1つの問題は、現在のMeshCardの光に対する可視性を考慮する必要があることです。Lumenは、ShadowMapまたはRTX光追跡を使用して、現在のMeshCardに対する光のオクルージョン割合（ShadowFactor）を決定することをサポートしています。
直接光計算の最後のポイントは、Diffuseの寄与項目のみを計算します。
ライト注入の最後の2つのステップは、MeshCardに対応するDiffuseAtlasとEmissiveAtlasまでにAlbedoとEmissive をサンプリングします。、MeshCardの最終ライト（間接+直接）のためにMipmapsを生成します。Mipmapsを生成するのは通常と同じく、バイリニアサンプリングを使用してフィルタリングしてから、高レベルのテクセルを生成します。

####３、Voxel Lighting Mips、Voxelライト注入（Lighting Injection）を更新する

上記のVoexlLightingの紹介から、カメラのワールド位置を中心としたVoxel Clipmapであることがわかります。そのため、カメラが移動すると、Clipmapも更新する必要があります。一度に更新する必要のあるボクセルの数を減らすために、次の最適化が行われます。
 
（1）フレームごとに最大1レベルのMipsが更新され、Voxel Clipmapの4レベルのMip更新の順序が次のとおりであることを確認します。
a。フレーム0、2、4、6、8、…はレベル0のmipを更新できます
b。フレーム1、5、9、13、17、…はレベル1のmipを更新できます
c。フレーム3、11、19、27、…レベル2のミップを更新できます
d。フレーム7、15、23、31、…はレベル3のmipを更新できます
 
（2）カメラが激しく動かない場合、理論的には、次の図に示すように、動きの方向から影響を受けるボクセルのみを更新する必要があります。


 
カメラの更新のほか、シーンでのPrimitiveの追加、削除、および変更も周囲のボクセルに影響を与えます。この戦略では、実際には、Lumenの実装でより一般的なPrimitiveUpdateBoundsを使用して、Clipmap Tile Boundと交差し、実際に更新必要があるVoxelの数を決定します。更新されたのはVoxelではなく、次に紹介するVisibilityBufferです。
VoxelLightingのライト解析・計算プロセスは、MeshDistanceFieldを使用して加速して交差します。Lumenは、現在のVoxel ClipmapのBoundboxで、この範囲にないすべてのObjectsとそれに対応するMeshDistanceFieldをかリングし、次にかリングされたMeshDistanceFieldサラウンドボックスを介して、どのVoxelをカバーするかを計算し、独自のインデックスを全てのVoxelをカバーするTraceパラメータに書き込みます。次のVoxel Trace Passでは、各Voxelは前のステップで入力されたMeshDistanceFiledを処理するだけで済みます。 Voxel Trace Passのエクスポートされたデータは、HitDistanceとHitObjectIndexの組み合わせを含むVisibilityBufferです。 VisibilityDataの構造は次のとおりです。
>uint32_t NormalizedHitDistance：8; //交差距離
>uint32_t HitObjectIndex：24; //オブジェクトID
最後のVoxelShading Passは、圧縮されたVisibilityBufferから最良の3つのMeshCardを取得して、Voxelのライトを解析・計算します。ここでのライト計算の重み係数は、AmbientCubeの係数を使うだけでなく、オブジェクトの透明度とMeshCardの可視性も考慮すべきです（VSMと類似、チェビシェフの不等式を使用して推定する）。
####4.GIVolumeを生成して計算する

ここでのGIVolumeは、即ち従来のIrradiance Volumeです。デフォルトでカメラから80メートルの世界（z軸）をカバーします。 実装の要件は次のとおりです。
>光源はVoxelLightingから供給され、ConeTraceを使用して照明します。デフォルトでは、各Volumeは16個のConeをサンプリングします。
>SH2を使用して各最終結果をエンコードします
>VoxelLightingの他、すべてのConeTraceはスカイライトもサンプリングします
履歴のライトデータを混合して、よりスムーズな変更を生成します

##三、ScreenSpace ProbeとIndirect Lightingの解析・計算

一般的なRTGI方案によると、MeshCardsと対応するLightingAtlas + MaterialAtlasを使用し、又VoxelLightingとGI Volumeの情報を使用すると、通常のゲームでGIを解析・計算するのに十分な情報があります。たとえば、次のように計算できます。
>１、光源：シーンを近景と遠景に分け、近景ならVoxelLightingを使用し、遠景ならDistantMeshCard（巨大なAmbientCubeに相当）を使用します。
>２、ライトの計算：PixelWorldPositionとPixelWorldNormalを使用して、一番近くて方向も一致しているVoxelで現在のGIを計算します。
>３、効率：ハーフスクリーン又はより低い解像度のGIRenderTargetを使用できます。
>４、効果：spatialとtemporal Filterを使用してライトを滑らかにし、いくつかの粗い手段で光漏れを処理します（Normal offsetとか、壁の厚さを制限するとか、stencilで屋内と屋外にマークを付けるとか、SDFでサンプリング点をオブジェクトから押し出すなど）。
VoxelLightingをGIVolumeに置き換えることもできます。これは、ライト計算でVolumeを取得する場合と重みを計算する場合にのみ異なります。
>１、光源：シーンを近景と遠景に分け、近景ならGI Volumeを使用し、遠景ならDistantMeshCard（巨大なAmbientCubeに相当）を使用します。
>２、ライトの計算：PixelWorldPositionとPixelWorldNormalを使用して、一番近くの若干のGI Volumeを取得します。
>３、効率：ハーフスクリーン又はより低い解像度のGIRenderTargetを使用できます。
>４、効果：効果：spatialとtemporal Filterを使用してライトを滑らかにし、いくつかの粗い手段で光漏れを処理します（Normal offsetとか、壁の厚さを制限するとか、stencilで屋内と屋外にマークを付けるとか、SDFでサンプリング点をオブジェクトから押し出すなど）。
より優れた効果が得られるため、Per PixelにPDF Importance Sampleに従ってサンプリング方向を生成してTrace MeshCardします。MeshCardのキャッシュデータには深度関連の情報が含まれているため、VoxelLightingのVisibilityWeigthの計算方法を直接模倣して可視性を推定でき、GGDIと類似しているオクルージョン効果を取得します。
Lumenは、SSGI、Detail MeshCard Trace、Voxel Lighting Trace、およびDistant Meshcard Traceを同時に使用して、最終的なライトを求めます。さまざまなTraceの作動距離と優先順位度は、次のように配置されます。
>１、SSGIの有効範囲はシーン全体です。つまり、SSGでHit までにTrace できる限り、SSGIリバウンド情報が使用されます。SSGIの概要については、《UE4.24 SSGI实现分析》（中国語注意）を参照してください。
>２、Detail MeshCard Traceの有効開始範囲は2メートル以内、Trace距離はカメラから40メートル以内です。VoexLightingを計算する場合と同様に、MeshCardのライト情報をサンプリングする時、VSMのような方法によって確率でオクルージョンを推定します。SSGIおよびMeshCardTraceによって決定されたProbeがある限り、VoxelLightingを使用しません。
>３、VoxelLighting Traceの有効範囲は、カメラから200メートル以内のピクセル範囲のみをカバーし、オクルージョン推定はConeに基づいて実装されます。
>４、Distant MeshCard Traceの有効範囲は200〜1000メートル以内です。
>５、半透過のオブジェクトへの処理には、GI Volumeが生成されます。
次の図に示すように、屋外のシーンでは、主にVoxelLighting（DistantMeshCardを含む）によって照明されたとわかります。


Probeは出現した後、LumenのIndirect Diffuse解析・計算プロセスは次のように調整されます。


>１、Downsample画面のサイズは1 / 16、1 / 16 + 1/32と小さくにし、[1 / 16、1 / 16]の部分はProbeによって生成され、残りの[1 / 16、1 / 32]は周りのprobeの空間情報や自己適応によって生成されます。中には、uniform placementのpassは16ピクセルの距離+ jitterのように配置し、adaptive placmentの部分は2つのpassに分割し、それぞれ8ピクセルと4ピクセルの距離で繰り返して、probeを放置する位置を見つけます。Adaptive Placementのアルゴリズムは、次のように述べられます。
Sampleの周りの4つのprobe{sample_probe（uv）、uv | uv + [（0,0）、（1,0）、（0,1）、（1,1）]）
bilinear weightを計算する
これらのprobeと現在のpositionの間の深度差と夾角を取得し、depth weight & corner weight を計算し、biliner weightと重ね合わせてfinalWeight にします。
すべてのfinalWeight <0の場合、サンプリングできる有効なProbeが周囲にないことを示し、新しいprobeを配置します。
>２、ConeTraceを使用してMeshCardとVoxelLightingおよびSSGIでprobeを生成するradianceをサンプリングし、probeに対し、sptial filterを実行して境界のサンプリング点を修復し、元のprobeデータをクリアせずにprobeをSHベースのデータに転送します。このように、probeには実際に2つのradianceデータ（octahedral map + shデュアルストレージ）があります。
>３、画面サイズにUpsample Probeし、temporal blend Indirect Diffuse。Upsample Probeには2つの主要な分岐があります。

hair stand以外のピクセルに対し、手順2で生成されたProbe SHを使用し、同じ重みのAdaptive Placementを使用して、SH混合を実行し、最終的なライトを計算します。

>Hairに対し、BRDF Importance Sample Weightを使用し、Probe octahedral mapをサンプリングして混合を実行し、最終的なライトを計算します。
RTX reflectionを使用しない場合、次のステップはindirect specularの解析・計算を実行し、最後にindirect diffuseと前のフレームのindirect diffuseを混合して、最終indirect diffuseを作ればエクスポートします。これで、LumenGI全体の計算が完了しました。Lumenは、RTXのように、すごく重い時間-周波数ドメインを頼って、ピクセル間の分散を抑制する訳ではありません。
 
*ルーメンの無限のバウンスはどのように達成されますか？*
MeshCardによってサンプリングされたVoxelLightingは前のフレームのデータであるため、MeshCardのバウンスデータは2番目のフレームから累積され、フレームごとにもう1つのバウンスが増えます。
 
*公式ドキュメントのSurfaceCacheはどこにありますか？*
MeshCard Lighting + Voxel Lightingは、公式ドキュメントのSurfaceCacheとほぼ同じです。
 
*World Space Probe Cache*
Cache方法、有効範囲、および更新戦略は、Voxel Lighting（3D Clipmap）に似ており、ただ保存されたデータがRadiance/Irradianceで、Traceの方法とデータ形式がScreen Space Probeというところはすこし違っています。
参考
1 . Jason Mitchel , Gary McTaggart and Chris Green , Shading in Valve’s Source Engine ,Advanced Real-Time Rendering in 3D Graphics and Games Course – SIGGRAPH 2006
2 . Cyril Crassin1,Fabrice Neyret1,Miguel Sainz,Simon Green4 Elmar Eisemann , Interactive Indirect Illumination Using Voxel Cone Tracing
3 . William Donnelly, Andrew Lauritzen, Variance Shadow Maps
4 . Zander Majercik Jean-Philippe Guertin,Derek Nowrouzezahrai,Morgan McGuire, Dynamic Diffuse Global Illumination with Ray-Traced Irradiance Fields
5 . Christopher C. Tanner, Christopher J. Migdal, and Michael T. Jones, The Clipmap: A Virtual Mipmap
6 . Thomas Engelhardt, Carsten Dachsbacher, Octahedron Environment Maps

---
UWA Technologyは、モバイル/VRなど様々なゲーム開発者向け、**パフォーマンス分析**と**最適化ソリューション**及び**コンサルティングサービス**を提供している会社でございます。

今なら、UWA GOTローカルツールが**15日間に無償試用**できます！！
よければ、ぜひ！

UWA公式サイト：https://jp.uwa4d.com
UWA GOT OnlineレポートDemo：https://jp.uwa4d.com/u/got/demo.html
UWA公式ブログ：https://blog.jp.uwa4d.com