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" を設定することによりトリガーできます。isTerraintrue に設定されている場合は、地表面とこのジオメトリの上方向を定義するために terrainUterrainV も指定する必要があります。有効なテレイン ジオメトリ HLBS マークアップを以下に示します。
テレイン ジオメトリ 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 属性も設定する必要があることに注意してください。さらに、terrainUterrainV は正規直交である必要があります。

ジオメトリにテレイン マークアップがあると、GeometryPacking プリコンピュート ステージで、特別なテレイン ジオメトリ パッキング ロジックが呼び出されます。この特別なパッキングにより、以下のように仮定されます。

  • すべてのジオメトリ メッシュが属する単一の Enlighten チャートのみが作成されます。
  • すべての頂点を terrainU および terrainV 方向に投影してライトマップ UV が生成されます
  • ライトマップ UV が U 方向と V 方向の両方で (0、1) の範囲になるよう再正規化されます
  • すべての AutoUV パラメーター、頂点リンク パラメーターなどは、テレイン ジオメトリに影響を与えないことに注意してください。

システム パッキング

ジオメトリ パッキングと同様に、テレイン システム向けに特別なシステム パッキングをトリガーする必要があります。システムをライトマップ LOD 生成に必要な特別なテレイン パッキングの対象とするには、マークアップする必要があります。

  • HLBS では、対象のシステムで使用される parameterSet の属性として requiresTerrainLODs="true" を設定するとトリガーされます。システムでテレイン パッキングと LOD 生成をトリガーするための有効な paramaterSet の定義は以下のとおりです。
テレインの ParamSet マークアップ
<parameterSet name="HighTerrain" id="0"
    outputPixelSize="1.0"
    clusterSize="2.0"
    irradBudget="64"
    samplesPerCluster="32"
    environmentResolution="16"
    requiresTerrainLODs="true"/>
  • requiresTerrainLODs プロパティは、低レベル API 経由でもアクセスできます (IPrecompBuildParameters)。
低レベル API でテレイン システム パッキングと LOD 生成をトリガー
virtual void SetRequiresTerrainLODs(bool b) = 0;
virtual bool RequiresTerrainLODs() const = 0;

上記のとおりマークされた parameterSet を使用して、既定のシステムがテレイン システムとして設定されると、いくつかの制限が適用されます。

  • そのシステムのすべてのジオメトリ (のインスタンス) は、テレイン ジオメトリになるようマークアップする必要があります (つまり、すべて isTerrain="true"terrainU および terrainV 方向の設定が必要です)
  • そのシステムのすべてのジオメトリの terrainUterrainV 方向は同じである必要があります
  • そのシステムのすべてのジオメトリの 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: システムの ParamSetrequiresTerrainPackingPadding="false" にする
  • 低レベル API: IPrecompBuildParameters::SetRequiresTerrainPackingPadding(false)

次に、Enlighten は相対的なワールド空間での位置に基づきシステムのすべてのインスタンスをパッキングします。これは、システムのすべてのインスタンスが同じサイズで一様のグリッドに配置されている場合に便利です。隣接する Enlighten テレイン システム間にシームがない、より大きなアトラスに Enlighten ライトマップを組み込むことができるためです。

また、特定の数の LOD の生成を要求することもできます。これは、以下のように行います。

  • HLBS: システムの ParamSetnumTerrainLODLevels="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 のまとめ

IPrecompInputGeometry マークアップ
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;


IPrecompBuildParameters マークアップ (システム マークアップ)
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;


IPrecompPackedSystem: 多数の LOD、LOD ごとの UV トランスフォームへのアクセス
virtual Geo::s32				GetNumLods() const = 0;
virtual const IPrecompPackedSystem*		GetLod(Geo::s32 lodIndex) const = 0;


IPrecompSystemRadiosity: ラジオシティ コアのアクセス
virtual Geo::s32				GetNumLods() const = 0;
virtual const RadSystemCore*			GetLodRadCore(Geo::s32 lodIndex) const = 0;


ILightTransportOutput: Light Transport のデバッグ出力
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 がプリコンピュート パイプラインで生成されている場合 (つまり、複数の radcorernt ファイルが生成されている場合)、GeoRadiosity により選択したシステムの実行時にそれらのラジオシティ コアを切り替えることができます。ラジオシティ コアは切り替えられた後、システムのライティングを計算するために使用されます。ライトマップの解像度の変更は Chart->RayOrigins ビューで確認できます (ただし、 Chart->Chart Texture ビューではできません)。GeoRadiosity のすべてのビューが LOD の切り替えで機能するわけではないことに注意してください。現在、以下のモードが機能します。

  • "Renderer: Scene" のすべてのレンダリング モード
  • Chart->Ray Origins