This is the documentation for Enlighten.
7.14. テレイン LOD
概要
Unreal Engine 4.8 サンプルのテレインの山々
Enlighten は、プレイヤーが水平線まで自由に移動できる、広いオープン ワールド レベルを有するゲームで使用できます。このようなタイプのシーンにおける一般的な機能は、ハイトフィールド テレインです。3.03 以降、Enlighten はテレインの可変の詳細度をサポートしており、ワールド全体で効率的なリアルタイムの Enlighten 更新を可能にします。
テレイン入力
Enlighten では、正規グリッドに配置された正方形のパッチの集合としてテレイン ジオメトリを提供する必要があります。典型的なシーンでの単一のパッチが以下に強調表示されています。大きなテレインは、数百のパッチからなります。
Unreal Engine 4.8 サンプルのテレインの山々
テレインの各パッチは、単一のテレイン入力ジオメトリとして Enlighten に提供されます。通常、テレインのパッチは類似したワールド空間ディメンションを持ち、複数のメッシュからなる場合があります。
大きなテレインを構成する多数のパッチは、Enlighten のシステムのセットにグループ分けする必要があります。各 Enlighten テレイン システムには、1 つ以上のテレインのパッチを割り当てることができます。
テレイン出力
テレインのパッチは、水平面への投射で定義される自然な UV のパラメーター表現を持ちます。これは、Enlighten がライトマップ UV を作成するために使用するパラメーター表現です。
入力シーンの各テレイン システムに対し、Enlighten プリコンピュート パイプラインが RadSystemCore オブジェクト (および対応するラジオシティ法線テクスチャ) のセットを生成します。各 RadSystemCore オブジェクトは、出力ライトマップの異なる詳細度を表します。詳細度が下がるごとに、解像度はおおよそ半分になります。解像度が下がるということは、解決する Enlighten ピクセルが少なくなり (実行時間の短縮)、メモリに格納するデータ (ピクセルごとのフォーム ファクターなど) が減ります。
デフォルトで、プリコンピュートはテレイン インスタンス UV に 0.5 ピクセルのパディングを追加します。このパディングは、各 LOD に異なる Enlighten UV トランスフォームを生成します。PackedGeometry の Enlighten UV は、単純なスケールと移動を含むこれらの UV トランスフォームを使用して、すべての LOD に再利用できます。Enlighten クラスタはすべてのテレイン LOD で同じであるため、クラスタごとのバッファ (入力ライティング、バウンスなど) に関するコードを変更する必要はありません。
詳細
ここでは、プリコンピュート パイプライン全体で、テレイン システム LOD データがどのように生成され、伝播されるかを詳細に説明します。
定義
- テレイン システム - テレイン パッチを表す Enlighten のシステムです
- テレイン ジオメトリ - テレイン システムの一部を表す Enlighten のジオメトリです。既定のテレイン システムには複数のテレイン ジオメトリが含まれる場合があります。
- テレイン メッシュ - テレイン ジオメトリの一部を表す Enlighten のメッシュです。テレイン ジオメトリに複数のテレイン メッシュが含まれる場合があります。
- テレイン ジオメトリ インスタンス - テレイン ジオメトリのインスタンスです。
- 水平面 - テレイン ハイトフィールドが定義されている面です。
- TerrainU - 水平面の U 方向を定義する方向 (単位ベクトル) です。
- TerrainV - 水平面の V 方向を定義する方向 (単位ベクトル) です。
- TerrainUp - TerrainU x TerrainV と定義される方向 (単位ベクトル) であり、テレインの上方向を表します。TerrainU と TerrainV を適切な値にし、(マイナスの TerrainUp 方向ではなく) 正しい TerrainUp 方向になるようにすることが重要です。
- テレイン ジオメトリ UV - ジオメトリ パッキング ステージから得られる UV です。
- インスタンス UV - IPrecompPackedInstance に格納されている UV であり、ライトマップからの読み取りのために使用されます。インスタンス UV は、インスタンス UV トランスフォームによりジオメトリ UV を変換することで取得できます (IPrecompPackedInstance にも格納されています)。
- ライトマップ LOD - 詳細度です。LOD0 が最も高解像度であり、LOD1 のピクセル数は LOD0 の 4 分の 1…という風に続きます。
ジオメトリ パッキング
このステージではジオメトリ UV (および Enlighten のチャートとその他データ) が生成されます。ジオメトリが (そのジオメトリがテレイン システムに属し、そのライトマップ LOD を生成したい場合に必要な) 特別なテレイン パッキングを受けるには、マーク アップする必要があります。
- HLBS では、ジオメトリの xml 属性に
isTerrain="true"
を設定することによりトリガーできます。isTerrain
がtrue
に設定されている場合は、地表面とこのジオメトリの上方向を定義するためにterrainU
とterrainV
も指定する必要があります。有効なテレイン ジオメトリ HLBS マークアップを以下に示します。
<geom name="LandscapeComponent_3_0" version="3" isTerrain="true" terrainU="1.000000 0.000000 0.000000" terrainV="0.000000 1.000000 0.000000"> <mesh [mesh 1 attributes go here] /> <mesh [mesh 2 attributes go here] /> <mesh [mesh ... attributes go here] /> </geom>
isTerrain
プロパティとterrainU
およびterrainV
方向のどちらも、(IPrecompInputGeometry
インターフェイス上の) 低レベル API を経由してアクセスできます。
virtual void SetIsTerrain(bool isTerrain) = 0; virtual bool IsTerrain() const = 0; virtual void SetTerrainU(Geo::v128 const& terrainU) = 0; virtual void SetTerrainV(Geo::v128 const& terrainV) = 0; virtual Geo::v128 const& GetTerrainU() const = 0; virtual Geo::v128 const& GetTerrainV() const = 0;
isTerrain
属性が設定されている場合、terrainU
および terrainV
属性も設定する必要があることに注意してください。さらに、terrainU
と terrainV
は正規直交である必要があります。
ジオメトリにテレイン マークアップがあると、GeometryPacking プリコンピュート ステージで、特別なテレイン ジオメトリ パッキング ロジックが呼び出されます。この特別なパッキングにより、以下のように仮定されます。
- すべてのジオメトリ メッシュが属する単一の Enlighten チャートのみが作成されます。
- すべての頂点を
terrainU
およびterrainV
方向に投影してライトマップ UV が生成されます - ライトマップ UV が U 方向と V 方向の両方で (0、1) の範囲になるよう再正規化されます
- すべての AutoUV パラメーター、頂点リンク パラメーターなどは、テレイン ジオメトリに影響を与えないことに注意してください。
システム パッキング
ジオメトリ パッキングと同様に、テレイン システム向けに特別なシステム パッキングをトリガーする必要があります。システムをライトマップ LOD 生成に必要な特別なテレイン パッキングの対象とするには、マークアップする必要があります。
- HLBS では、対象のシステムで使用される parameterSet の属性として
requiresTerrainLODs="true"
を設定するとトリガーされます。システムでテレイン パッキングと LOD 生成をトリガーするための有効な paramaterSet の定義は以下のとおりです。
<parameterSet name="HighTerrain" id="0" outputPixelSize="1.0" clusterSize="2.0" irradBudget="64" samplesPerCluster="32" environmentResolution="16" requiresTerrainLODs="true"/>
- requiresTerrainLODs プロパティは、低レベル API 経由でもアクセスできます (
IPrecompBuildParameters
)。
virtual void SetRequiresTerrainLODs(bool b) = 0; virtual bool RequiresTerrainLODs() const = 0;
上記のとおりマークされた parameterSet を使用して、既定のシステムがテレイン システムとして設定されると、いくつかの制限が適用されます。
- そのシステムのすべてのジオメトリ (のインスタンス) は、テレイン ジオメトリになるようマークアップする必要があります (つまり、すべて
isTerrain="true"
とterrainU
およびterrainV
方向の設定が必要です) - そのシステムのすべてのジオメトリの
terrainU
とterrainV
方向は同じである必要があります - そのシステムのすべてのジオメトリの
pixelSize
は同じである必要があります - そのシステムのすべてのジオメトリの
blockSize
は同じである必要があります
チャート LOD チェーン生成
テレイン ジオメトリには (ジオメトリあたり) チャートは 1 つだけであることに注意してください。それぞれのチャートには、terrainU
および terrainV
方向への (ワールド空間) 投影の範囲と pixelSize
で定義される、ライトマップ (アトラス) サイズがあります。これがベース (LOD0) 解像度です。各チャートについて、毎回 pixelSize
を倍にしてより高い LOD (1、2…) が得られます (また、チャート ライトマップ サイズが x 方向と y 方向の両方で常に 2 の倍数になるよう丸めます)。LOD チェーン生成は、すべてのチャートが 2x2 になると停止します。
たとえばシステムに 6 つのジオメトリ (のインスタンス) があり、それらのジオメトリが異なるワールド空間ディメンションを持つ場合は以下のとおりです (単純化のため、terrainU
および terrainV
方向に一致)。
- Geom1 (200m, 150m)
- Geom2 (100m, 100m)
- Geom3 (100m, 50m)
ピクセル サイズは 1m になるよう設定されています。以下のチャート LOD が得られます。
- LOD0: Geom1(200x150), Geom2(100x100), Geom3(100x50)m pixelSize = 1
- LOD1: Geom1(100x76), Geom2(50x50), Geom3(50x25), pixelSize = 2
- LOD2: Geom1(50x38), Geom2(26x26), Geom3(26x14), pixelSize = 4
- LOD3: Geom1(26x20), Geom2(14x14), Geom3(14x8), pixelSize = 8
- LOD4: Geom1(14x10), Geom2(8x8), Geom3(8x4), pixelSize = 16
- LOD5: Geom1(8x6), Geom2(4x4), Geom3(4x2), pixelSize = 32
- LOD6: Geom1(4x4), Geom2(2x2), Geom3(2x2), pixelSize = 64
- LOD7: Geom1(2x2), Geom2(2x2), Geom3(2x2), pixelSize = 128
システム パッキングとシステム LOD 生成
すべてのチャート LOD で、チャート (ジオメトリあたり 1 つ) はアトラスに集約されます。各チャートから 1 つずつ IPrecompPackedInstance
オブジェクトが作成され、UV はシステム ライトマップ (アトラス) の最終的な座標を指すように設定されます。また、UV トランスフォームも各 IPrecompPackedInstance
オブジェクトに設定され、生のパッキングされたジオメトリ UV (IPrecompPackedGeometry
に格納) から最終的なライトマップ UV に変換できるようにします。つまり、IPrecompPackedGeometry
から UV を読み取ってライトマップ ピクセルにアクセスし、そのジオメトリを表す IPrecompPackedInstance
に格納されている UV トランスフォームで変換できます。最後に、アトラス テクスチャ、すべてのパッキングされたインスタンス、追加データを含む IPrecompPackedSystem
が作成されます。
明示的に無効にされていない限り、最終的なパッキングされたチャートの周囲に 0.5 ピクセルの境界が生成されます。無効にする方法は以下のとおりです。
- HLBS: システムの
ParamSet
をrequiresTerrainPackingPadding="false"
にする - 低レベル API:
IPrecompBuildParameters::SetRequiresTerrainPackingPadding(false)
次に、Enlighten は相対的なワールド空間での位置に基づきシステムのすべてのインスタンスをパッキングします。これは、システムのすべてのインスタンスが同じサイズで一様のグリッドに配置されている場合に便利です。隣接する Enlighten テレイン システム間にシームがない、より大きなアトラスに Enlighten ライトマップを組み込むことができるためです。
また、特定の数の LOD の生成を要求することもできます。これは、以下のように行います。
- HLBS: システムの
ParamSet
でnumTerrainLODLevels="X"
を設定します。X は正の整数です。 - 低レベル API:
IPrecompBuildParameters::SetNumTerrainLODLevels(Geo::s32)
requiresTerrainPackingPadding="false"
と組み合わせて使用し、同一の Enlighten UV ストリームを持つ LOD を指定した数だけ作成し、より大きなミップマップを適用したアトラスで使用できるようにすることも可能です。
IPrecompPackedSystem
を作成するプロセスは、すべての LOD レベルで繰り返されます。これにより、アトラスのパッキングされたシステムの解像度がどんどん小さくなります。パッキングされたテレイン ジオメトリの生 UV と、IPrecompPackedInstances で報告されるインスタンスごとの UV トランスフォームを使用することにより、あらゆる LOD でライトマップ (アトラス) にアクセスできます。
次に、さまざまな LOD を表す IPrecompPackedSystems
が (それ自体が LOD0 を表す) 単一の IPrecompPackedSystem
オブジェクトに組み込まれます。他の LOD には、以下を呼び出してアクセスできます。
virtual Geo::s32 GetNumLods() const = 0; virtual const IPrecompPackedSystem* GetLod(Geo::s32 lodIndex) const = 0;
パッキングされたシステムで GetLod(0)
を呼び出すと、それ自体が返されます。他の LOD は、GetLod(s32 index)
メソッドに適切なインデックスを渡すことでアクセスできます。
上の例では、プリコンピュート システム パッキング ステージは、1 つの IPrecompPackedSystem
(mainSystem
と呼びます) を返します。これで、以下が実現します。
mainSystem->GetNumLods()
は8
を返しますmainSystem->GetLod(0)
はmainSystem
へのポインターを返しますmainSystem
には、3 つのチャート (200x150、100x100、100x50) を持つアトラスがあります。このアトラスは、パッキングされたジオメトリの UV と適切なIPrecompPackedInstance}}
({{mainSystem
のもの) のUV トランスフォームを使用することによりアクセスできます。mainSystem
は、パッキングされたシステムの主要な LOD0 バージョンを表します。これは、LOD の適用を考慮する必要がないすべてのプリコンピュート ステージ (プレクラスタリング、クラスタリングなど) で使用されるシステムのバージョンです。- (たとえば) LOD3 は以下を呼び出してアクセスできます。
lod3System = mainSystem->GetLod(3)
. lod3System
には 3 つのチャート (26x20, 14x14, 14x8) を持つアトラスがあります。このアトラスは、パッキングされたジオメトリの UV と適切なIPrecompPackedInstance}}
({{lod3System
のもの) のUV トランスフォームを使用することによりアクセスできます。
用語の説明部分の画像に示すテレイン パッチに対するテレイン システム パッキングの結果を以下に示します。このシステムは 6 つのテレイン ジオメトリ (のインスタンス) を含みます。それぞれが最終的なアトラスで 1 つのチャートになります。基本の LOD(0) では、それぞれの解像度は約 20x20 です。各チャートが 2x2 になるまでの連続したスクリーンショットで、解像度の減少が確認できます。また、(それぞれの LOD で) 各チャートが 0.5 ピクセルの境界で囲まれていることに注意してください。LOD0 の代わりに LOD4 を使うと、解決する必要があるライトマップ ピクセルの数が 2600 からわずか 24 に減ります。
プリコンピュートの出力
テレイン システムとジオメトリ マークアップの後、そのシステムのさまざまな LOD が生成され、プリコンピュート パイプライン全体に伝播されます。これにより、テレイン システム向けに複数のラジオシティ コア ファイル (および法線テクスチャ ファイル) の生成が始まります。各ラジオシティ コア (および .rnt ファイル) は、そのシステムの異なる LOD を表します。テレイン システムの名称が "TerrainPatch01" であり、上の画像のような LOD を持つ場合 (LOD0、…LOD4)、HLBS は以下の radcore (および rnt) ファイル (SSE ソルバーのターゲット向け) を生成します。
TerrainPatch01.rc.see
TerrainPatch01.rc_LOD_1.see
TerrainPatch01.rc_LOD_2.see
TerrainPatch01.rc_LOD_3.see
TerrainPatch01.rc_LOD_4.see
TerrainPatch01.rnt
TerrainPatch01_LOD_1.rnt
TerrainPatch01_LOD_2.rnt
TerrainPatch01_LOD_3.rnt
TerrainPatch01_LOD_4.rnt
LOD を行うシステムが使用されていなかったかのように、LOD0 が同じ名前のラジオシティ コアで表されていることに注意してください。
これらのラジオシティ コアと rnt
テクスチャは、ライト バウンスを解決するためにランタイム API (以下で説明) で使用できるようになりました。
HLBS が使用されていない場合、LOD ラジオシティ コアには IPrecompSystemRadiosity
経由でアクセスできます。
virtual Geo::s32 GetNumLods() const = 0; virtual const RadSystemCore* GetLodRadCore(Geo::s32 lodIndex) const = 0;
プリコンピュート API のまとめ
virtual void SetIsTerrain(bool isTerrain) = 0; virtual bool IsTerrain() const = 0; virtual void SetTerrainU(Geo::v128 const& terrainU) = 0; virtual void SetTerrainV(Geo::v128 const& terrainV) = 0; virtual Geo::v128 const& GetTerrainU() const = 0; virtual Geo::v128 const& GetTerrainV() const = 0;
virtual void SetRequiresTerrainLODs(bool b) = 0; virtual bool RequiresTerrainLODs() const = 0; virtual void SetRequiresTerrainPackingPadding(bool b) = 0; virtual bool RequiresTerrainPackingPadding() const = 0; virtual void SetNumTerrainLODLevels(Geo::s32 v) = 0; virtual Geo::s32 GetNumTerrainLODLevels() const = 0;
virtual Geo::s32 GetNumLods() const = 0; virtual const IPrecompPackedSystem* GetLod(Geo::s32 lodIndex) const = 0;
virtual Geo::s32 GetNumLods() const = 0; virtual const RadSystemCore* GetLodRadCore(Geo::s32 lodIndex) const = 0;
virtual Geo::s32 GetNumLODs() const = 0; virtual const ILightTransportOutput* GetLOD(Geo::s32 lodIndex) const = 0;
ランタイム
テレイン LOD が機能するには、Enlighten が同じシステムを異なる解像度で解決できる必要があります。これは、テレイン システムに対する複数のラジオシティ コアを生成し、各 RadSystemCore
が特定の LOD に属するようにすると、プリコンピュートで処理されます。インテグレーションは、カメラ位置に基づいて、どの LOD を解決する必要があるかを判断する必要があります。ほとんどの場合、大半のテレインは遠くにあると想定されるので、これは完全な LOD セットの小さなサブセットになります。必要な LOD サブセットが解決されると、入力として解決されたセットのうち最高品質の LOD のみを使用し、Enlighten::ResampleBounce()
ステージを実行する必要があります。これにより、バウンスを可能な最高品質レベルで伝えることができます。
既定のタイミングで解決しなければならない LOD のサブセットが少ない場合もあるため、すぐに解決する必要がある RadSystemCore
のみをメモリに保持することをお勧めします。これにより、サブシステムのストリーミングの負荷と大きなワールドのメモリ要件を大きく緩和できます。
低レベル ランタイム
Enlighten の低レベル API から新しく呼び出す関数はありません。低レベル API のユーザーは、インテグレーションがシステムあたり複数の RadSystemCore
を解決し、最高品質のソリューションからのみバウンスをリサンプリングできるようにする必要があります。ライトマップ テクスチャの内容を更新する前にレンダリングで使用されないように、ある程度の対策をとる必要があります。新しい LOD に切り替えると、解決のスケジュールイングから、テクスチャ リソースでデータを確認できるようになるまで、テクスチャに古いデータが存在する可能性があるため、これはさらに重要になります。準備が整う前のテクスチャを使用すると、LOD がソリューションの内外で切り替えられるため、アーティファクトの発生につながります。
高レベル ランタイム
HLRT のユーザーの場合、テレイン LOD を適切に扱うために注意すべきいくつかの変更があります。Enlighten 3.03 より前は、Enlighten::System}}
と Enlighten::RadSystemCore
の間に 1 対 1 のマッピングがありました。しかし、Enlighten 3.03 では、Enlighten::System
ごとに複数の{{RadSystemCore
が存在することが可能です。RadSystemCore
ごとに追加のサポート データおよびメモリが必要であるため、このデータは SystemSolutionSpace
という新しいオブジェクト タイプにまとめられています。このインターフェイスは Enlighten::ISystemSolutionSpace
クラスを介して露出されます。
詳細については、高レベル ランタイムセクションを参照してください。
GeoRadiosity のサポート
テレイン システムの LOD がプリコンピュート パイプラインで生成されている場合 (つまり、複数の radcore
と rnt
ファイルが生成されている場合)、GeoRadiosity により選択したシステムの実行時にそれらのラジオシティ コアを切り替えることができます。ラジオシティ コアは切り替えられた後、システムのライティングを計算するために使用されます。ライトマップの解像度の変更は Chart->RayOrigins ビューで確認できます (ただし、 Chart->Chart Texture ビューではできません)。GeoRadiosity のすべてのビューが LOD の切り替えで機能するわけではないことに注意してください。現在、以下のモードが機能します。
- "Renderer: Scene" のすべてのレンダリング モード
- Chart->Ray Origins