» VR開発メモトップへ

Unity ライトマップの焼き方メモ

最終更新日:2022年06月04日

Unityでのライトマップの焼き方の解説とTipsです。そもそもライトマップとは何かというところから、引っかかりやすそうなポイントを順番にフォローしていく形で書いてみました(そのうちもうちょっと画像増やしたいです)。

なお、著者は絵作りがそんなに上手くないので参考程度に!

更新履歴

(2022年6月4日)「マルチシーンでライトマップを有効にする方法」のコードを修正
(2022年5月31日)ライトマップUVのサンプル画像を追加
(2022年5月2日)「TerrainにTreeの影が落ちない」を追加
(2022年4月16日)画像を「Escape Miku!」のものに変更、その他修正
(2022年4月6日)Adaptive Probe Volumesについて追記


そもそもライトマップとは

3Dグラフィックスにおいてライティングはとても重い処理で、特に間接光の表現はリアルタイムで行うのが難しいため、3Dメッシュ上の光の強度や色をあらかじめ「ライトマップ」というテクスチャに焼き込んでおく(「ベイク(bake)する」とよく言います)テクニックがしばしば用いられます。

Unityでは、適切なシーン設定を行った上で、Lightingウィンドウでシーンのライトマップを焼くことができます。生成したライトマップはシーン名と同じ名前のフォルダに保存され、ビルドすると実行ファイルに含まれます。

たとえば上の画像のシーンだと、このようなテクスチャがプロジェクト内に生成されています。

広いシーンのライトマップをきちんと焼こうとすると、PCを一晩動かしっぱなしにして焼くようなこともあり、失敗することも多々あります。結構大変です。

ライトマップのメリットとして、スマートフォンやOculus Questのようなモバイルデバイスでも低負荷でリアリスティックな絵を出せる場合があります。デメリットとして、焼くのが大変なのと、ライトマップのテクスチャぶん配布サイズが増えます。また、焼き込まれた光はリアルタイムに変化させることができません。

また、広大なシーンではライトマップのサイズに限界が出てくるため、ライトマップは主に小規模から中規模のシーンで用います。

Unityでとりあえずライトマップを焼いてみる

Unityで新規プロジェクトを3Dテンプレートで作成してください。シーンにPlaneとCubeあたりを適当に作成します。

ライトマップを焼くためのシーン設定をします。まず、Directional LightのModeをBakedに設定します。また、ライトマップを焼きたいすべてのオブジェクト、ここではPlaneとCubeについて、Inspectorの右上のStaticをオンにします。これによってそれらは「動かないオブジェクト」とみなされ、ライトマップの計算に含まれるようになります。

Window > Rendering > LightingでLightingウィンドウを開きます。Unity 2020以降ではデフォルトでライトマップが無効化されていますが、New Lighting Settingsボタンをクリックするとライトマップが焼けるようになります。

LightingウィンドウのGenerate Lightingボタンを押し、しばらく待って、焼き終わったらCubeを動かしてみてください。影がCubeの動きについてこなくてその場に残っているようであればライトマップがきちんと焼けています。下の画像のようにできれば成功です。

Projectウィンドウでシーンと同じ名前のフォルダにライトマップのテクスチャが生成されていることを確認してください。

Lightingウィンドウには設定がたくさんありますが、混乱したときはとりあえず新しくシーンを作るか、New Lighting Settingsで新しい設定ファイルを作って(Unity 2020以降)デフォルトに戻してみてください。ただし、最低限以下の2つの設定だけは確認しておいてください。

Auto Generate

Generate Lightingボタンの左にAuto Generateというチェックがあります。これをオンにするとシーンの変更に応じて自動的にライトマップが焼かれます。ただし、オンだとライトマップ等のファイル群が生成・更新されませんので、本番ではオフにしてGenerate Lightingを手動でクリックする必要があります。

Lightmapper

PCに高性能なビデオカードを積んでいる場合はProgressive GPUに変更しましょう。Progressive CPUよりずっと高速に焼けます。ビデオメモリが足りない場合はProgressive CPUにフォールバックされるので注意が必要です。

ライトマップを速く焼けるようにする

さて、ここまでで単純なシーンは焼けるようになったと思いますが、少し複雑なシーンを焼こうとすると、やたら時間がかかって全然焼き終わらない上に、だいたい設定ミスをしていて上手くいかないと思います。たぶんこの辺で9割くらいの人が挫折します。

ライトマップはLightingウィンドウの下記のいくつかの設定を変更するだけでとても速く焼けるようになります。実際、小さいシーンでProgressive GPUなら数秒ほどで済みます(もちろん結果はかなり雑になりますが)。速く焼ける設定にしてライティングを調整したり試し焼きをしてから、パラメーターの数値を上げてきちんと焼くというワークフローがおすすめです。ライトマップを焼くのを練習したり、機能を調べるときにも、まずは速く焼ける設定に変更しましょう。

Lightmap Resolutionを下げる

ライトマップの解像度です。焼き時間に大きく影響します。大きくすると影がくっきりし、下げると影がぼやけますがとても速く焼けます。1まで下げると影の形がまったく分からなくなってしまうので、5や10程度に下げます。

各種サンプリング数を下げる

Direct Samples、Indirect Samples、Environment Samplesをそれぞれ最低の1、8、8に下げてしまいます。特にIndirect Samplesの影響が大きいようで、Indirect Samplesだけ8にしてもいいかもしれません。

Asset Storeからインポートしたアセットを焼く

さて、こうしてライトマップの焼き方を覚えて意気揚々とAsset Store等からインポートしたアセットを焼こうとすると、これまた全然上手くいかないと思います。

一番多いのは、影がきちんと落ちなかったり、明らかにおかしな形の影が落ちるケースです。下の画像が典型的な例です。

ライトマップ用のUVを生成する必要があります。3Dモデルを選択して、インスペクタのModelタブのGenerate Lightmap UVsをオンにしてApplyで再インポートしてください。これで焼けるようになることが結構多いです。

あと繰り返しになりますが、ライトがBakedになっていること、オブジェクトにStaticのチェックが入っていることを確認してください。慣れるまでは忘れがちです。

また、アセットに不要なライトや発光するオブジェクトが含まれていることがあります。Light Explorerを使用すると、シーンに配置されているライティングに影響するオブジェクトを一覧表示できますので、これで確認してみてください。Window > Rendering > Light Explorerで開きます。

動くオブジェクトのライティング

ここまでで動かないオブジェクトの影や間接光を焼くことはできるようになったと思いますが、動くオブジェクト(たとえばプレイヤーキャラクター)にはこれらは反映されず、見た目が不自然になってしまいます。

「ライトプローブ」を配置すると、Staticでないオブジェクトにも事前計算された周囲の光がある程度反映されるようになります。シーン内の必要と思われる場所に適宜ばらまいておくと、オブジェクトの位置によって補間して使用されます。

ライトプローブを設置するには、Hierarchyウィンドウで右クリック > Light > Light Probe Groupを設置して、Edit Light Probesボタンを押してAdd Probeで追加していきます。

リアルタイムシャドウとの兼ね合いについて

ライトマップで焼いた影とリアルタイムシャドウの影の兼ね合いについて、適宜Lighting Modeを設定します。

Subtractive

とにかく軽くしたいときはSubtractiveにします。LightmapとDirectional Lightmapが生成され、Directional ModeをNon-Directionalに変更するとLightmapのみが生成されます。

メインの1つのDirectional Lightのみからリアルタイムシャドウが落ちます。Subtractiveには、ライトマップの影にリアルタイムシャドウの影が二重に落ちてしまう弱点があります。Environment > Realtime Shadow Colorを調整して同じような(溶け込む)色にする必要があります。

Shadowmask

高品質にしたいときはShadowmaskにします。Subtractiveで生成されるテクスチャに加え、Shadowmaskが生成されます。ライトマップの影とリアルタイムシャドウの影がきちんと混じり、複数のMixedのライトからリアルタイムシャドウの影が落ちます。

Baked Indirect

間接光のみがライトマップに焼かれ、直接光の影はリアルタイムシャドウになります。

Tipsおよびトラブルシューティング

ライトマップを焼く際にありがちなエラーや困りごとをいくつかまとめてみました。

小さなオブジェクトのライトマップが綺麗に焼けない

たとえば広い大地に落ちている小石や、部屋に置いてある小さなランプ等のライトマップを焼くと、不自然な境目のある影が発生したりして汚くなりがちです。こうしたオブジェクトではライトマップを焼かず、ライトプローブを使用することで見た目がよくなり、また、ライトマップテクスチャの節約になります。

具体的には、Mesh RendererのReceive Global IlluminationをLight Probesに変更します。

屋内のライトマップを焼く場合

デフォルト設定だと、壁や天井で囲まれた室内にも空の色が落ちて青く照らされてしまいます。Reflection Probeを設置してBox Projectionをオンにし、部屋の形にあわせてサイズを調整してください。

リフレクションプローブはいわば影響範囲を限定したスカイボックスです。たとえばMetalicを1にしたStandardシェーダーのオブジェクトを配置すると、リフレクションプローブの範囲内はリフレクションプローブが、範囲外ではスカイボックスが映り込むようになります。

また、密閉された部屋だと光がどこからも届かず真っ暗になってしまうので、現実と同じようにライトや窓から差し込む光をArea LightやPoint Lightで配置します。Indirect Intensityを上げると部屋の隅や影に光が回りこんでやわらかい感じになります。

影をやわらかくしたい

Area Lightでサイズのある光源を作ると影のエッジがやわらかくなります。また、BakedのポイントライトはBaked Shadow Radiusで影のエッジをやわらかくすることができます(単位メートル)。

現実世界の光源は必ず大きさがありますので、基本これらを使って大きさのある光源を設置するのがよさそうです。ためしに現実世界で周りを見回してみてください。輪郭がくっきりした影はほとんど存在しないと思います。

部屋の隅を暗くしたい

Ambient Occlusionをオンにします。影の濃さはIndirect Contributionで調整するのが良さそうです。

メッシュごとにライトマップ解像度を調整したい

Sceneビューのプルダウンメニューから表示をBaked Lightmapに変更して、さらにメニューの一番下のShow Lightmap Resolutionをオンにすると、メッシュごとのライトマップ解像度を視覚的に確認できます。解像度が過剰だったり不足しているメッシュはMesh RendererのScale in Lightmapで調整できます。

ライトマップのサイズを小さくしたい

LightingウィンドウでLightmap Sizeを調整するほか、Directional ModeをNon-Directionalに変更するとDirectional Lightmapが生成されなくなります。詳細は以下を参照してください。

また、ライトマップを焼いたあとで、焼かれたライトマップテクスチャのインポート設定を変更することで容量を調整することもできます。

ライトのモードをMixedやBakedに設定できない

LightingウィンドウのBaked Global Illuminationがオフになっているとこれらの設定が無効化されます。

スマートフォンで影が汚い・変な色が入る

Project SettingsでスマホのLightmap EncodingがLow Qualityになっている可能性があります。プラットフォームごとに別設定になっていますので、NormalかHighに上げてみてください。Unityのドキュメントでは下記ページに解説があります。

TerrainにTreeの影が落ちない

TerrainにSpeedTreeのファイルを直接アサインしているとライトマップが焼けません。SpeedTreeの木をいったんシーンに配置して、Projectウィンドウにドラッグしてプレハブ化し、Staticのチェックを入れてTerrainにアサインし直すと焼けるようになります。

スクリプトでライトマップを利用する際のTips

マルチシーンでライトマップを有効にする方法

マルチシーンの場合、現在アクティブなシーンのライティング設定およびライトマップが使用されます。以下のようにLoadSceneMode.Additiveでシーンを読み込んだのちにSetActiveSceneを呼ぶことで、読み込んだシーンのライトマップが有効になります。

SceneManager.LoadScene(sceneName, LoadSceneMode.Additive);

// LoadSceneでシーンが読み込まれるのは次のフレームになるため1フレーム待つ
// (LoadSceneAsyncで読み込む場合は不要)
await UniTask.NextFrame();

SceneManager.SetActiveScene(SceneManager.GetSceneByName(sceneName));

Bakeryについて

Unity標準のプログレッシブライトマッパーの代わりに、Bakeryという有料アセットがVRChatのワールド制作者の間でよく使用されているようです。

古いバージョンのUnityでもGPUを使用してライトマップを焼け、Unity標準のライトマッパーより綺麗に焼けるとの話があります。WindowsおよびNVIDIAのGPU専用です(あくまでベイクに必要で、Bakeryで焼いたライトマップはどこでも使えます)。

BakeryはUnityとは異なる光源系を用います。たとえばDirectional LightにBakery Direct Lightコンポーネントをアタッチする必要があります。「Match lightmapped to real-time」ボタンを押すとUnityのライトと同じパラメーターがセットされます。

さらに、環境光を得るには、Bakery > Create > Skylightを作成して、青っぽい色を設定して「Match this light to scene skybok」ボタンを押します。

Bakery > Render lightmap…を開いてRenderボタンを押すとライトマップが焼けます(初回はいろいろメッセージが出てきます)。

SettingsをAdvancedにしてRTX modeを有効にするとGeForce RTXのアクセラレーションを利用するようです。

書いた人:こりん(@korinVR
» VR開発メモトップへ