ライトマップとグローバルイルミネーション

はじめに

注意: Qt 6.4 現在、ライトマップのベイクは初期のテクニカルプレビューの状態です。機能、品質、API の変更は将来のリリースで行われる可能性があります。

ベイクされたライトマップは、DirectionalLightPointLightSpotLight などのライトからの直接照明を、ライトによってキャストされる影を含めて、事前に生成することができます。実行時に、フラグメントシェーダで適切な計算を行い、シャドウの場 合、コストのかかる可能性のあるシャドウマップをリアルタイムで生成す る代わりに、事前に生成されたイメージマップがサンプリングされます。

ライトマップはModel ごとに生成されます。Model に複数のサブメッシュがあり、したがって複数のマテリアルに関連付け られている場合でも、モデル全体に対して生成されるライトマップ画像は 1 つになります。

ライトマップはレイトレーシングを使用して生成されます。レイトレーシングは性質上、適切なオクルージョン(「光は壁を通り抜けない」)を提供し、ライティングとシャドウマッピングのためのリアルタイム技術よりもリアルな影を提供する可能性があります。

さらに重要なのは、ライトマップは間接照明の焼き付けを可能にし、グローバルイルミネーションのソリューションを提供することです。これは、シーン内の他のサーフェスから反射された光線を考慮に入れます。

以下は簡単な例です。このシーンには4つのRectangleと1つのSphereモデルがあり、DirectionalLight は下を向いていて、PointLight 。Rectangleモデルは0度と90度回転しています。DirectionalLight の方向に対してすべて平行か垂直なので、リアルタイムのライティング計算の限界を誇張しています。

つ目の画像では、5つのモデルすべてに対してライトマップをベイクした後、ライトマップを有効にしてシーンをレンダリングしています。両方のライトは完全にベイクされた状態に設定されています。つまり、直接照明と間接照明の両方がベイクされています。間接照明は256samples 、最大3bounces 。その結果、ライトマップはノイズ除去された。これにより、かなりリアルな画像が得られます。

リアルタイム照明

球体、長方形、2つのライトによるシンプルなシーン

完全にベイクされたライティング

両方のライトをフルベイクに設定した同じシーン

以下は、ライトマップの結果がどのように達成されたかを示すスニペットです。違いはusedInBakedLighting,bakeMode,bakedLightmap プロパティにあります。この例では、texelsPerUnit プロパティを使用してライトマップのサイズを縮小し、ディスクスペースを節約してアプリケーションのロード時間を短縮しています。

DirectionalLight {
    bakeMode: Light.BakeModeAll

    eulerRotation.x: -90
    brightness: 0.5
    castsShadow: true
    shadowFactor: 75
}
PointLight {
    bakeMode: Light.BakeModeAll

    y: 200
    z: 100
    color: "#d9c62b"
    castsShadow: true
    shadowFactor: 75
}
Model {
    usedInBakedLighting: true
    bakedLightmap: BakedLightmap {
        enabled: true
        key: "sphere1"
    }

    source: "#Sphere"
    materials: PrincipledMaterial { }
    y: 100
}
Model {
    usedInBakedLighting: true
    bakedLightmap: BakedLightmap {
        enabled: true
        key: "rect1"
    }

    source: "#Rectangle"
    materials: PrincipledMaterial { }
    eulerRotation.x: -90
    scale: Qt.vector3d(10, 10, 10)
}

// ... three additional Rectangle models, with rotations 0, 90, and -90

上記の例では、完全にベイクされたライトを使用しました。ライトは、ダイレクトライティングとシャドウマッピングをリアルタイムで実行しながら、間接照明にのみベイクドライティングを使用するように設定することもできます。下のシーンには5つのポイントライトがあり、2つ目のスクリーンショットでは、そのすべてがBakeModeIndirect に設定されています。ダイレクトライティングとシャドウは同じに見えますが、2枚目の画像はグローバルイルミネーションが追加されているため、かなり良く見えます。

リアルタイム・ライティング

スポンザとスザンヌのモデルと5点照明のシーン

ベイクされた間接照明を追加した状態

同じシーンで、間接照明がベイクされ、直接照明がリアルタイムで表示される

ライトマップで作業する際の重要な考慮事項

ベイクされたライティングに寄与するライトは、そのbakeMode プロパティがLight.BakeModeIndirect またはLight.BakeModeAll のいずれかに設定されています。後者は、その特定のライトの直接寄与と間接寄与の両方がライトマップから来ていることを示します。直接寄与には常にシャドウも含まれます。一方、ライトマップを使用する意図が、特定のライトに対してシーンに間接照明を追加するだけであり、リアルタイムで直接照明を計算する(シャドウマッピングを実行する)場合は、ライトはLight.BakeModeIndirect を代わりに使用します。

注意: ライトマップは一般的に言って、トランスフォーム、ジオメトリ、マテリアルに関して静的なモデルに適しています。ベイクドライティングに参加するライトも同様です。

たとえば、eulerRotation プロパティをアニメートすることによってModel を回転させるシーンは、そのModel にライトマップを適用すると、視覚的に正しくない結果になります。その特定のModel のレンダリング結果は不正確になります。なぜなら、事前に生成されたライトマップは、オブジェクトの単一の回転状態しかキャプチャしないからです。別の例を挙げると、モデルのサブメッシュの1つのマテリアルが、時間(アニメーション)またはユーザのインタラクションに基づいて、baseColor プロパティを動的に変更する場合も同様です。ライトマップは、与えられた1つのマテリアルbaseColor しかキャプチャできません。ライトも同様です。たとえば、DirectionalLight 、時間とともに回転したり、明るさや色などを変えたりするものは、ベイクド・ライティングには適していません。

注意: 一方、ライトマッピングをいつ使うかは、常にデザイナーの選択です。特にBakeModeIndirect 、ライトマップされたシーン内のオブジェクトの一部がダイナミックな動作を採用していても、その結果が視覚的に満足できるシーンがある可能性があります。

ライトマッピングは、複雑なエンジンとツール機能です。エンジンのレンダリングパイプラインのいくつかの部分を置き換え、再実装します。ライトマップをベイクする際には、根本的に異なるレンダリングモデルで動作しますが、同じシーン構造、アセットデータ、エンジンデータ構造を消費し、相互運用します。レイトレーシングベースの結果は、リアルタイムの代替案を上回ることが多く、時には大幅に上回ることもありますが、その代償として、関係するモデルやライトの強制的な静的性などの制限や、時にはライトマッピングに特有の品質やレンダリングアーチファクトの問題が生じます。

実際には、どのタイプのライティングをいつ使うかは、デザイナーの芸術的な選択になります。bakeMode また、複雑で大規模なシーンでは、シーンの特定のセクションに適していると判断されるものや、どのようなモデル、マテリアル、ダイナミックなビヘイビアが存在するかによって、異なるライトに対して3つすべてを利用することも大いにありえます。ライトマッピングは、どのシーンやアプリケーションでも有効にできる単純なオン/オフの切り替えスイッチではなく、与えられたシーンのライティングニーズを慎重に評価することを前提とした強力な機能であり、多くの場合、シーンのコンテンツとビヘイビアをそれに応じて設計し、最終的なアプローチと関連する設定を決定する前に、さまざまなライトマップのベイクとクオリティ設定を検討し、テストするテストアンドチューンのループと組み合わせる必要があります。

注意: ライトマップは両面サーフェスをサポートしていません。リアルタイムライティングでは、Material.NoCullingcull mode を持つマテリアルは、フラグメントの向きに基づいて法線を自動的に反転します。ライトマップのベイクはビュー空間では動作しないため、これはライトマップのオプションではありません。したがって、これに依存するようなモデルにはベイクドライティングを避けてください。

ライトマップのベイク

ライトマップのベイクに関連するプロパティとタイプは、直接照明と間接照明をキャプチャし、アプリケーションの後続の実行でレンダラーが使用できるイメージマップを生成するオフラインプロセスを意味します:

Qt 6.4 では、ライトマップのベイク処理は手動でトリガーする必要があります。コマンドライン引数--bake-lightmaps が存在するか、環境変数QT_QUICK3D_BAKE_LIGHTMAPS1 (またはその他のゼロ以外の値)に設定されている場合、エンジンはベイクモードで動作し、ベイクが完了するとアプリケーションを終了します。デバッグ出力に出力されるメッセージを確認することで、ベイク処理の手順を追うことができます。その結果、シーン内のすべてのベイク済みライトマップを含むバイナリファイル(デフォルトではlightmaps.bin )が現在の作業ディレクトリに書き込まれます。また、ライトマップ全体とノイズ除去に必要な追加データを含む.raw ファイルも作成されます。各ライトマップは、BakedLightmap::key からの一意のキーによってファイル内で一意に識別されます。

ライトマップされたシーンを準備するには、主に以下の手順を踏みます:

  • ライトマップを使用するモデルと、ライトマップに寄与するモデルを特定します。ライトマップされたシーンの一部であるモデルは、Model::usedInBakedLighting を true に設定します。ライトマップされる(つまり、ライトマップがベイクされる)モデルは、さらにModel::bakedLightmap を有効なBakedLightmap オブジェクトに設定する必要があります。これは、特定の Model オブジェクトインスタンスを永続的に識別する一意のキーを提供します(これは、Qt が永続的なディスクストレージでモデルデータを識別するためにキーを必要とするためです)。静的なジオメトリ、トランスフォーム、マテリアルを持つモデルだけが、ランタイムにライトマップされたときに正しい結果を持つことが保証されます。最も一般的なのは、位置、回転、スケールが動的に変化したりアニメーションしたりするなど、時間の経過とともに静的でないワールドトランスフォームにつながるものは、モデルの参加資格を失うということです。しかし、アーティスティックなニーズがこれを上書きすることもあります。特に、間接照明のベイクに貢献するだけで、それ自体はライトマップされないモデルの場合です。このようなモデルの場合、ダイナミックトランスフォームを使用することが、視覚的に許容されることがよくありますが、これは常にモデルと問題のシーンに依存します。
  • どのライトがどの程度寄与すべきかを特定します。Light::bakeMode には、3つのオプションがあります:
    • デフォルトのLight.BakeModeDisabledは、事実上、すべてのライトマッピングの目的でライトを無視します。
    • Light.BakeModeIndirectは、シーンにグローバルイルミネーション(間接照明)のレベルを持たせることが唯一の目的であり、他の方法でライトのレンダリング結果に影響を与えない場合、多くの場合、「安全な」選択です。このモードでは、レンダラーは、ディフューズ、スペキュラ、スカイ/環境寄与、シャドウマッピングを含むすべてのライティングを、標準的なリアルタイムテクニックを使用してこのライトに対して実行し続けます。ただし、ライトはプリベイクされたデータを使用して間接照明に寄与し、標準のリアルタイム照明計算では手を付けられないサーフェスを照らす可能性があります。
    • Light.BakeModeAllは、与えられたシーンに何が適切かについてのデザイナーの評価に基づいて、特定のライトにのみ使用されるオプションです。このモードでは、シャドウを含め、ライトからのすべての寄与がベイクされます。Qt 6.4 では、スペキュラライティングはベイクされたライティングの一部としてサポートされていないため、このようなライトはスペキュラの寄与を持ちません。一方、レイトレースされ、ベイクされたシャドウが生成され、ライトに対して適切なオクルージョンがあります(例えば、「壁を通り抜ける」ことはありません)。さらに、BakeModeIndirectと同様に間接照明もベイクされます。
  • ベイクモードでシーン(アプリケーション)を実行し、ライトマップが正常に生成されていることを確認します。Qt 6.4では、アプリケーションはライトマップされたシーンが最初に表示されるような構造になっているか、qml ツールのようなQtMLビューアで当該シーンを読み込むことができるようになっています。ベイクが完了すると、その進行状況はコンソール/デバッグ出力で追うことができ、アプリケーションは終了します。
  • シーン(アプリケーション)を普通に実行し、ライトマップがロードされた状態でどのように見えるかを確認します。その後、チューニングを開始します:
    • モデルによっては、texelsPerUnit をデフォルト値からもっと小さくするのが理にかなっています。これは特にビルトインプリミティブや、ジオメトリが単純なものに当てはまります。これにより、ライトマップが小さくなり、ベイク時間が短縮されます。初めてベイクするときは、デフォルト値で十分です。
    • Lightmapperオブジェクトは、合理的なデフォルト値を持つ数多くの設定を公開していますが、設計者の期待に合うようにこれらのいくつかを調整する必要がある可能性は低くありません。例えば、samplesbounces は間接照明の質に影響するように変更でき、indirectLightFactor は間接照明の寄与をより顕著にすることができます。アーティファクト、特にシャドウ周辺が発生する場合は、bias を微調整できます。
    • 生成されたライトマップのノイズ除去は不可欠です。間接照明はパストレーシングを使用して計算され、samples の数によってノイズの多い画像が生成されます。サンプル数を増やすとノイズは減りますが、ライトマップの生成に必要な時間が長くなります。サンプル数に関係なく、バイナリファイルに保存された32ビットRGBA浮動小数点画像である生成されたライトマップに対してノイズ除去を実行することは、ほとんどの場合、意味があります。

Qt 6.5では、DebugView を使ってインタラクティブに実行時のソリューションを提供します。 ツール(Tools)の下にボタンがあり、それを押すとベイク処理が開始されます。現在の処理を示すウィンドウがポップアップします。キャンセルするには、キャンセルボタンを押すか、このウィンドウを閉じます。完了すると、ライトマップのバイナリがカレントディレクトリに書き込まれます。

ノイズ除去

以下はコーネルボックスのシーンの例で、最初に256samples と最大3bounces でベイクしたライトマップを使ってレンダリングします。2番目の例では、生成された画像ファイルはノイズ除去され、結果はかなり良くなり、ノイズはほとんどなくなりました。

オリジナル

1点ライト、フルベイクされたライトマップを持つコーネルボックスのシーン

ノイズ除去済み

ライトマップがノイズ除去されたコーネルボックスのシーン

ノイズ除去はベイクされたライトマップごとに自動的に行われます。作業ディレクトリに既存のベイク済み.raw ライトマップファイルが存在する場合、DebugViewDenoise ボタンをクリックすることで、ノイズ除去だけを行うことも可能です。また、--denoise-lightmaps 引数を指定してアプリケーションを呼び出すことで、ノイズ除去を行うことも可能です。ノイズ除去の強さを調整するには、denoiseSigma プロパティを使用します。

ライトマップUV

ライトマップUV座標は、通常のテクスチャリングと同じUVデータを使用しません。ライトマップを使用してレンダリングする場合、ライトマップをサンプリングするときに UV0 と UV1 のどちらのデータもレンダラーによって使用されません。その代わりに、メッシュに追加の専用UVチャンネルがあり、ライトマップの目的に適した方法でレイアウトされたUVチャートを含みます。これは、オーバーラップを避け、適切な場所にパディングを持つことを含みます。通常のUVデータにはそのような要件はなく、複数の頂点に同じUとV座標を使いたい場合も大いにあり得ます。

適切なUVセットを生成するプロセスはライトマップUVアンラップと呼ばれます。Qtはライトマップをベイクするときにこれを実行し、結果のメッシュをライトマップ・ファイルに保存して、互換性のあるメッシュが常にロードされ、生成されたライトマップに使用されるようにします。つまり、モデルが常にベイクドライティングを使用するのであれば、ソースメッシュファイルをアプリケーションに同梱する必要はありません。

ライトマップのテクスチャサイズ

すべてのサブメッシュを含む各モデルについて、ライトマップベイク処理は、ライトマップUV生成フェーズで適切なライトマップテクスチャサイズを決定します。これは品質、パフォーマンス、リソース使用量(ディスクとメモリの両方)に影響します。

デフォルトは多くの場合適切で、特に中〜高複雑度のモデルでは調整の必要はありません。

しかし、非常に単純なモデルの場合、手動でサイズを小さくすることが望ましい場合があります。ライトマップのサイズを小さくしても、視覚的に見栄えの良い結果を得られる可能性がある一方、アセット(ライトマップ画像)のサイズを小さくすると、ディスク容量とメモリの両方を節約できるからです。これを行うには、texelsPerUnit を適切な小さい数値に設定します。実際のライトマップの幅と高さは、モデルのサイズとジオメトリに応じて、texelsPerUnit と一致するようにテクセル密度を近似しようとします。

値を変更するときは、必ずライトマップをリベイクし、変更したライトマップサイズの影響を評価するために結果を目視で確認する必要があります。

ランタイムでのライトマップの使用

プリベイクされたライトマップをランタイムで使用する場合に関連するプロパティとタイプです:

ベイクが正常に完了すると、(コマンドライン引数や環境変数を設定せずに)アプリケーションを通常どおりに実行すると、生成されたライトマップ画像を拾って正しくレンダリングできるようになります。必要であれば、アプリケーションはライトマップを別の場所に置いたり、Qt Resource System を経由して実行ファイルの一部として送信することができます。これは、source プロパティによって有効になります。

上記の球体と4つの矩形のサンプルコードを例にすると、ベイク処理によって、ベイクされたメッシュとライトマップをすべて含むlightmaps.bin ファイルが生成されます。アプリケーションは、このファイルをsource で指定された場所に、エンジンが見つけられるように格納する必要があります。

Qt Quick 3D - ベイクドライトマップの例も参照してください

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.