This is the documentation for Enlighten.

7.1.1. 低レベル ランタイムのウォークスルー


スケジューリングとリソースの扱いを完全に制御する必要がない限りは、高レベル ランタイムの使用をお勧めします。

低レベル ランタイム API は、いくつかのコンポーネントで構成されており、さまざまなプラットフォームに対応し、幅広い構成を可能とする十分な柔軟性を有しています。要件に応じて、ゲームにランタイムを実装する多くの方法があります。

このウォークスルーでは、低レベル ランタイム APIを使用してさまざまなランタイム コンポーネントを組み合わせる方法を示す、単純な例について説明します。単純なランタイムを機能させることに集中するため、スケジューリング、代替のアルベドと入力ライティングのオプション、さまざまな出力形式、Enlighten SDK の任意に選択できる部分については触れません。

ワークフロー

Enlighten のシステム用にテクスチャを生成するプロセスは、ライティング情報を次々更新し、「ソルバー」を動作させる API 呼び出しのループを中心としています。他のすべてのランタイム モジュール (アルベドなど) は、このループの動作を補助するためにあります。プローブ セットの生成プロセスは非常に類似しており、ライティング情報を共有します。まず、Enlighten のシステムを説明します。

この図は、以下のステップと関連する API 呼び出しを示しています。

  1. 入力ライティング バッファに入力ライトを書き込みます: Enlighten::DoWriteInputLightingTask
  2. GPU が計算したダスター値またはキャッシュされた入力ライティング バッファを追加します (任意): Enlighten::AddDusterValuesToInputWorkspace, Enlighten::AddCachedValuesToInputWorkspace
  3. バウンス、アルベド、およびエミッシブを適用した入力ライティング バッファを確定させ、一時的な解決のためにライティングの違いを計算します。Enlighten::DoEndInputLightingTask
  4. ラジオシティを解決します: Enlighten::SolveIrradianceTask

DoWriteInputLightingTask

Enlighten::DoWriteInputLightingTask は、従来のライトの寄与 (Enlighten::InputLight) をライティング バッファに書き込みます。バッファ内の以前のライティングはすべて消去されます。これは、この呼び出しの前に Enlighten::Add[Duster/Cached]ValuesToInputWorkspace ユーティリティ関数により追加された値が上書きされることを意味します。したがって、これらの関数によって追加されるカスタマイズされたライティングは、Enlighten::DoWriteInputLightingTask の実行後に追加する必要があります。

ほぼすべてプラットフォームで、タスクに必要なメモリ量はわずかです。このバッファのサイズは Enlighten::CalcRequiredWorkspaceMemory により計算されます。

Add[Duster/Cached]ValuesToInputWorkspace

これはすべてのカスタマイズされた入力ライティング (たとえば GPU で計算されたダスター値) を出力ライティング バッファに書き込みます。

DoEndInputLightingTask

このステップでは、サーフェス アルベドを入力ライティングに適用し、バウンスおよびエミッシブ ライティングを追加し、必要に応じてラジオシティ解決の際の一時的な最適化に使用されるライティングの差分値を計算します。

一時的な最適化により、最後の更新からライティングが大きく変わっていないことを検出した場合に、ライトマップ解決タスクの処理をスキップすることが可能になります。ただし、ライティングの更新をスキップするには、過去のライティングを再利用し、ライティングのエラーを蓄積できるだけの十分な永続データが必要です。

TextureAlbedo アプローチでは、Enlighten 出力 UV 空間に配置され生成される、ダウンサンプリングされたアルベド テクスチャを使用します。このテクスチャは使いやすく、一般的なマテリアルをサポートしており、通常は GPU でレンダリングされます。

SolveIrradianceTask

一時的な解決機能を構成するため、Enlighten::SolveIrradianceTask は一時的しきい値と一時的イプシロン値を入力として受け入れます。ライティングの変化と現在の強度の割合がしきい値よりも大きい場合、出力ピクセルを解決する必要はありません。

  • しきい値は [0;1] の範囲内です。0.01 という値で十分な結果が得られ、完全な解決と比較しても明らかな違いはありません (0.01 は GeoRadiosity のデフォルト設定です)。負のしきい値を渡した場合、一時的な最適化は無効になります。
  • イプシロン値は、小さな適正値であり、ジッタとゼロ除算を避けるために使用します。出力値の範囲より小さくする必要があります。通常は、デフォルト値の 0.0001 のままで問題ありません。

一時的な解決を使用しても、解決によってすべてのピクセルに書き込まれるとは保証されていないため、出力テクスチャは永続的である必要があります。先ほど述べたとおり、ライティング差分値の積算合計を格納するために、バウンス データも永続的である必要があります。

バッファ サイズ

バウンス データ バッファのサイズは、Enlighten::CalcRequiredBounceOutputSize により計算され、割り当てる際に 0 にする必要があります。一時的な解決が必要な場合、解決タスクではそのバッファのライティング差分値の積算合計を格納するため、Enlighten::DoEndInputLightingTask で使用されるバウンス データは永続的である必要があります。

一時的な解決を使用する際、差分値を計算するために Enlighten::DoEndInputLightingTask にも前のフレームのライティング バッファを渡す必要があります。従って、ライティング バッファはダブル バッファリングを行い、永続的である必要があります。一時的な解決が不要な場合は、前のライティング バッファ ポインターを NULL に設定できます。

エミッシブ環境と一時的な最適化

エミッシブ環境に一時的な最適化を使用する場合、SetEnvironmentLightValues を解決ごとに 1 度だけ呼び出し、環境に対して適切な差分値が正しく計算されるようにします。そうしないと、アニメート化された、または変化する環境で一貫性のない結果が生じます。

FreezeIrradianceTask

一時的な解決を使用する場合、いくつかの更新要件を満たす必要があります。これは、入力ライティング バッファは前のフレームのライティング差分のみを格納しますが、ラジオシティ解決はライティング更新をスキップするかどうかを判断するための差分値集計で、この差分データに依存しているためです。

具体的には、システムの入力ライティングの更新では、再度更新する前にこの入力ライティングを参照するすべてのラジオシティ システムを更新する必要があります。これは、入力ライティング バッファに依存するすべてのシステムが、バッファに格納されている値を参照し、積算合計を適切に更新できるようにすることが最適化する上で必要であるためです。

そうしないと、一部のシステムがライティングの差異を捉えられず、更新の頻度が低下し、重大なライティング アーティファクトが発生する恐れがあります。これは、環境に対する要件とまったく同じです (環境を特別な入力ライティング バッファとして捉えると理解しやすくなります)。

しかし、各システムで Enlighten::SolveIrradianceTask を呼び出す必要はなく、その代わりにシステムの一部のサブセットで Enlighten::FreezeIrradianceTask を呼び出すことができます。この関数は、出力値を計算することなく、ライトの差分を追跡するための最低限のハウスキーピング処理だけを実施するため、非常に高速です。「より重要な」システム (たとえば、カメラの近くのシステム) の更新を円滑に行いつつ、パフォーマンスを抑えるために、さまざまなシステムのライティングの更新を異なるペースで行う場合に役立ちます。

FreezeInputLightingBuffer

一部のシステムで入力ライティング バッファの更新の頻度を下げることも可能です。これを行う際は、ライティング バッファで入力ライティングの計算の代わりに Enlighten::FreezeInputLightingBuffer を呼び出します。これにより、以前のライティングの変更が「二重に計上」されないようにします。(これによって出力に視覚的アーティファクトが発生することはありませんが、更新された値が必要以上に計算されるため、パフォーマンスが低下します。)