This is the documentation for Enlighten.

6.5.1. 高レベル ランタイム


このページでは、High Level Runtime APIを使用して Enlighten ランタイム ラジオシティ更新を実行する方法について説明します。

更新マネージャー オブジェクトは、Enlighten ランタイム ラジオシティ更新を実行するための簡単なインターフェイスを提供します。

IUpdateManagerのメンバー関数を異なるスレッドから呼び出すことは、安全ではありません。更新マネージャーを作成するスレッドを 1 つ選び、そのスレッドからのみやり取りを行います。

名前に Enqueue を含む関数はすぐには実行されず、非同期の実行のためキューされます。このような非同期関数が完了したかどうかは、IUpdateManager::FlushCommands を呼び出し、保留中のコマンドが完了するまで現在のスレッドをブロックしない限り、保証されません。IUpdateManagerメンバー関数がポインター型の引数を受ける場合、この関数のドキュメントで説明されているとおり、呼び出し元として、自分で参照されたオブジェクトのライフタイムを確認する必要があります。

Enlighten ラジオシティ更新を実行するには、レンダリング対象に対応したライト、シャドウ、マテリアルの情報を提供します。それに対し、レンダラーで Enlighten 出力が使用されます。エンジンと高レベル ランタイム間のコミュニケーションを簡素化するには、レンダラーを実行するスレッドと同じスレッドから高レベル ランタイムを実行することをお勧めします。

出力テクスチャ

高レベル ランタイムを使用するには、出力テクスチャの実装を提供する必要があります。このオブジェクトは、必要なグラフィクス API を使用して CPU のテクスチャに書き込む効率的な方法を実装します。

各出力テクスチャ オブジェクトは、書き込み先のエンジンのテクスチャ リソースへの参照を含んでいる必要があります。

IGpuTextureと IGpuTextureUpdaterインターフェイスを実装します。すぐに使用するには、実装サンプル Dx11TextureUpdaterをコピーします。主要な関数は以下のとおりです。

一部のケースでは、特定のターゲット ハードウェアまたはグラフィックス API 専用の実装を作成すると、さらに効率的に更新することができます。たとえば、一部のプラットフォームは CPU が直接書き込みできる共有メモリに割り当てられたテクスチャ リソースを提供します。

初期設定

MultithreadCpuUpdateManager::Create を呼び出し、非同期更新をサポートする高レベル ランタイムのインスタンスを作成します。UpdateManagerPropertiesを提供し、ラジオシティ計算を構成します。

デフォルトのプロパティでは、品質とコストの適切なバランスが保たれます。

プロパティ

デフォルト

ライトマップ出力タイプ

ディレクショナル イラディアンス

ライトマップ出力形式

半精度浮動小数点 (FP16)

プローブ出力タイプ

L1 SH

プローブ出力形式

非圧縮浮動小数点

キューブマップ出力形式

半精度浮動小数点 (FP16)

最初はこれらのデフォルト値を使うことをお勧めしますが、必要に応じて後からカスタマイズできます。

更新マネージャーの作成
Enlighten::UpdateManagerProperties properties;
Geo::GeoUniqueReleasePtr<Enlighten::IUpdateManager> updateManager = Enlighten::MultithreadCpuUpdateManager::Create(properties);

MultithreadCpuUpdateManager::Create は、エラーおよび警告メッセージ用のロガーを設定していない場合に空値を返します。

データのロード

Enlighten ランタイム データのまとまりをロードする際、高レベル ランタイムに追加します。

システム、プローブ セット、キューブマップそれぞれにランタイム オブジェクトを割り当てるには、IUpdateManager::AllocateSystemIUpdateManager::AllocateProbeSet、または IUpdateManager::AllocateCubeMap を呼び出します。ラジオシティデータに加え、選択した出力タイプと形式に応じた出力テクスチャを提供します。システムにライトマップがない場合、RadSystemCore または出力テクスチャを受け取らない IUpdateManager::AllocateSystem オーバーロードを使用します。

割り当てられたランタイム オブジェクトとともに IUpdateManager::EnqeueueAddSystemIUpdateManager::EnqueueAddProbeSet、または IUpdateManager::EnqueueAddCubeMap を呼び出します。

ライトマップを有するシステムの割り当てと追加
Enlighten::IGpuTexture* outputTextures[Enlighten::ENLIGHTEN_NUM_OUTPUT_TEXTURE_TYPES] = { nullptr };
outputTextures[Enlighten::ENLIGHTEN_OUTPUT_IRRADIANCE] = irradianceTexture;
outputTextures[Enlighten::ENLIGHTEN_OUTPUT_DIRECTIONAL] = directionalTexture;
 
Enlighten::BaseSystem* object = updateManager->AllocateSystem(radiosityCore, inputWorkspace, directionalVisibility, outputTextures);
 
updateManager->EnqueueAddSystem(object);

このシステムのインスタンスにプローブを使ってライティングしている場合、ラジオシティ コアと出力テクスチャを必要としない IUpdateManager::AllocateSystem のオーバーロードを使用します。

各オブジェクトを構成するには、追加した直後に EnqueueWorkerFunctorCommand または EnqueueSetObjectParameter を使用して BaseSystem、BaseProbeSet、または BaseCubeMap のプロパティ セッター関数を呼び出します。

これらのランタイム オブジェクトのメンバー関数を直接呼び出すことはできません。デバッグ ビルドで行うと、致命的なエラーが報告されます。

空のライティングを有効にするには、プロパティ セッター BaseSystem::SetEmissiveEnvironmentBaseProbeSet::SetEmissiveEnvironment、または BaseCubeMap::SetEmissiveEnvironment を呼び出します。

C++11 を使用している場合、ラムダで EnqueueWorkerFunctorCommand を呼び出します。

プロパティの設定 (C++11)
Enlighten::EnqueueWorkerFunctorCommand(updateManager.GetPtr(), [=](Enlighten::IUpdateManagerWorker* worker)
{
    object->SetEmissiveEnvironment(environmentGuid);
});


C++11 を使用していない場合は、EnqueueSetObjectParameter を呼び出します。

プロパティの設定 (C++03)
Enlighten::EnqueueSetObjectParameter(updateManager.GetPtr(), object, &Enlighten::BaseSystem::SetEmissiveEnvironment, environmentGuid);

Enlighten::EnqueueSetObjectParameter(updateManager.GetPtr(), object, &Enlighten::BaseSystem::SetEmissiveEnvironment, environmentGuid);
各システムにマテリアル カラーを指定するには、プロパティ セッター BaseSystem::SetAlbedoData を呼び出します。

アルベドの設定 (C++11)
Enlighten::EnqueueWorkerFunctorCommand(updateManager.GetPtr(), [=](Enlighten::IUpdateManagerWorker* worker)
{
    Enlighten::SystemAlbedoData AlbedoData;
    AlbedoData.m_AlbedoBuffer = albedoBuffer;
    object->SetAlbedoData(AlbedoData);
});

各フレーム

前のフレームから入力に変更がある場合、Enlighten にデータを提供します。

IUpdateManager::EnqueueUpdateEmissiveEnvironment を呼び出して環境ライティングを更新します。

提供する環境ライティング値のアレイは、少なくとも非同期コマンドが完了するまで存在している必要があります。このアレイは、更新マネージャーと同時に作成し、更新マネージャーを解放した後に削除することをお勧めします。

光源を提供するには、ワールドのすべての,光源に対して IUpdateManager::EnqueueUpdateLight を呼び出します。SpotlightPointLight、および DirectionalLight を含め、一般的なライトのタイプはすでにサポートされています。エンジンの光源データからは、各ライトのタイプを簡単に構築できます。

ディレクショナル ライトの追加
Enlighten::DirectionalLight light;
light.m_Intensity = intensity;
light.m_Direction = direction;
updateManager->EnqueueUpdateLight(lightGuid, light);

ライトの強度プロパティは、光源から照らされるサーフェスに到達する赤、緑、青の光の量を定義します。

ポイントとスポットライトには、どちらもフォールオフ テーブルが必要です。物理法則に基づく逆 2 乗のフォールオフに対してはデフォルトのフォールオフ テーブルを使用します。

逆 2 乗のフォールオフ テーブルの作成
Geo::GeoUniquePtr<Enlighten::InputLightFalloffTable> falloffTable(GEO_NEW(Enlighten::InputLightFalloffTable));

指定するライト フォールオフ テーブルは、少なくとも更新マネージャーが解放されるまで存在している必要があります。このオブジェクトは、更新マネージャーと同時に作成し、更新マネージャーを解放した後に削除することをお勧めします。

ポイント ライトの追加
Enlighten::PointLight light;
light.m_Intensity = intensity;
light.m_Position = position;
light.m_Radius = radius;
light.m_CutOff = cutoff;
light.m_FalloffTable = falloffTable;
updateManager->EnqueueUpdateLight(lightGuid, light);

更新マネージャーは、IUpdateManager::EnqueueUpdateLight の前の呼び出しから変化がなかったライトを自動的に検出し、必要のない計算をスキップします。前のフレームから変化がなかった光源が多数ある場合、IUpdateManager::EnqueueUpdateLight をスキップして時間を節約できます。

最後に、IUpdateManager::Update を呼び出して、新しい出力がないか調べ、非同期ラジオシティ更新を開始します。

ラジオシティ更新のエンキュー
updateManager->Update()

待機中の更新がタイミングよく処理されるようにするには、フレームごとに一貫して IUpdateManager::Update を呼び出します。

データのアンロード

ワールドから除去したそれぞれのライトについて、IUpdateManager::EnqueueRemoveLight を呼び出します。

アンロードする各オブジェクトについて、IUpdateManager::EnqueueRemoveSystemIUpdateManager::EnqueueRemoveProbeSet、または IUpdateManager::EnqueueRemoveCubeMap を呼び出します。

高レベル ランタイムではオブジェクトが除去されたあと、次の IUpdateManager::Update の最中に IGpuTexture::Release の実装を呼び出します。IGpuTexture::Release 実装内の IGpuTexture オブジェクトを安全に削除します。

システム、プローブ セット、キューブマップを追加する際に提供したラジオシティ データは、非同期除去コマンドが完了するまで使用中になる可能性があります。除去コマンドが完了した後で安全にラジオシティ データを削除するには、カスタム コマンドをエンキューします。

ラジオシティ データの安全な削除 (C++11)
updateManager->EnqueueRemoveSystem(systemGuid);
 
Enlighten::EnqueueWorkerFunctorCommand(updateManager.GetPtr(), [=](Enlighten::IUpdateManagerWorker* worker)
{
    // ここでラジオシティ データを削除します
});

非同期除去コマンドが完了するまで、BaseSystem::SetAlbedoData に提供した AlbedoBuffer または EmissiveBuffer オブジェクトは削除しないでください。