太郎Work

Unityとかで困ったこと等を残しておきます

AdaptiveProbeVolumeさわってみた

概要

Adaptive Probe Volume (APV) とは、従来の Lightmap や LightProbe を置き換えることが可能な、Unityの新しいグローバルイルミネーション (GI) システムです。

以下は、各システムの長所・短所を比較した表です

システム 長所 短所
LightProbe ベイクしていないメッシュに適用可能 配置が面倒、適用範囲がメッシュ単位、Instancing描画バッチがされない
LightMap 高品質 事前ベイクが必須、ベイクに時間がかかる、解像度の調整必須、UV2次第では切れ目が見える
APV メッシュに依存せず高品質、プローブの自動配置が可能 グリッド間隔に依存するため光漏れが発生する場合がある

APVは、高品質な結果を得られる反面、課題もありますがモバイル環境でも利用可能である点など、今後に期待できる機能です。将来的には Dynamic APV が実装される予定であり、拡張にも期待しています。
docs.unity3d.com
https://portal.productboard.com/unity/1-unity-platform-rendering-visual-effects/c/1939-precomputed-realtime-gi-dynamic-apv?&utm_medium=social&utm_source=starter_share

GI Off
GI On

GameObject設定

APVを利用する際のGameObject設定について説明します。

Mesh Renderer

  • Contribute Global Illumination
    ベイクに含めたいメッシュの場合チェックを入れてGIに影響を与える設定にします。
  • Recieve Global Illumination
    APVとしてベイクする場合は必ずLight Probesを選択してください。

Adaptive Probe Volume

APVは Create > Light > Adaptive Probe Volumeから作成します。

Mode
Scene シーンに存在するstaticメッシュを全て覆います。意図しないサイズで生成される場合があるので注意が必要です。
Global ロード中の全てのシーンを結合した範囲を覆います。ただし、シーンごとに個別に指定したほうが無難です。
Local 特定の範囲のみ囲ってベイクを行います。複数を組み合わせて使用することも可能です。
Subdivision Override

Overrideは基本不要ですが、ベイクサイズの削減に使用します。
詳細は ベイクサイズの削減方法 を参照してください。

Geometry Settings
  • Override Renderer Filters
    対象となるLayer設定の上書きが可能です。
  • Fill Empty Spaces
    メッシュが存在しない空間にもプローブを生成するかを指定します。ファイルサイズが大幅に増加する可能性があるため注意してください。
Bake Probe Volumes

LightingWindowからのベイクも可能ですが、ここからAPVのみのベイクも実行できます。

ライティング設定

APVでもWindow > Lightingメニューを使って設定が可能です。

Scene

Lighting Settings Asset

LightingSettingsは従来とは異なり、APVの場合、細かい調整が不要です。ただし、一部のパラメータはAPVが参照するため注意が必要です。

Mixed Lighting

  • Baked Global Illumination
    チェックをオンにしないと、ライトコンポーネントのMixed, Bakeモードが有効になりません。
  • Lighting Mode
    ライトマップベイクの設定です
Lightmapping Settings

ほとんどはライトマップ用のパラメータですが、Lightmap ResolutionやAlbedo Boostといった一部のパラメータはAPVにも影響を受けます。
ライトマップは生成されませんが、内部的にGI生成に使用するAlbedo、Emissionマップを生成しており、そのテクスチャを元にAPVも生成しているためです。
Scene View上での確認方法

Lightmap Resolutionは小さすぎるとGI精度が落ちてしまい、高すぎる場合のデメリットはわかっていないですがライトマップと併用する場合もあるためここは今まで通り設定する必要があります。

ここでのAlbedo、EmissionマップはシェーダのMetaパスによる出力になっており、その結果をテクスチャとして生成します。

以下の画像はLightmap Resolutionを変更した際のAPVの変化になります。

40 texel per unit

Baked Global Illumination Emission
APV Preview

0.1 texel per unit

Baked Global Illumination Emission
APV Preview

分かりやすいように極端に解像度を落としましたが、解像度が低すぎると色が正しく再現されない場合があります。
そのためライトマップを焼かない場合でもベイク結果を確認しながらTexelサイズを意識する必要があります。

Adaptive Probe Volumes

APV固有の設定項目について紹介します。

Baking Mode
Single Scene 現在アクティブなシーンに対してベイクします
Baking Set Baking Setアセットを使用して複数シーンのベイクを行います

Probe Offset

APVは等間隔でプローブが配置されますが、基準点をずらしてベイクすることで見た目の改善やベイクサイズの改善が可能です。
Probe Offsetの調整 で詳細を記載しています。

Min Probe Spacing

プローブ間隔の最小距離です。
初期値は1.0mに設定されています。この値を小さくするほど高解像度になりますが、結果としてベイクデータサイズも大きくなります。例えば、以下のような設定例が挙げられます。

  • 屋内シーンや小規模なエリアでは0.5m〜1.0m程度
  • 屋外などの大規模なシーンでは1.0m〜2.0m程度

ベイクデータサイズの調整は、 ベイクサイズの最適化 を参照してください。

Max Probe Spacing

プローブ間隔の最大距離です。
初期値は左から2番目の4階層(Min Probe Spacingが1mの場合27m)が設定されています。
ベイクデータサイズの調整は、ベイクサイズの最適化 を参照してください。

LayerMask

ベイク対象となるメッシュのLayerを指定します。特定のオブジェクトのみベイク対象としたい場合に便利です。

Min Renderer Size

ベイク対象とするRendererの最小サイズを指定します。デフォルト値は 0.1 です。

Sky Occlusion Settings

空(Skybox)によって遮られるライティングの影響を調整する設定です。ただし本記事では検証していないため割愛しています。

Probe Invalidity Settings

プローブの無効化状態を制御する設定です。
Dilation、Virtual Offsetともに光漏れを抑制する機能です。光漏れの軽減を参照してください。

Generate Lighting

ボタンを押すことでライトマップ、プローブ、リフレクションプローブのベイクを一括で実行します。
以下のファイルサイズに注意してください。

  • Scenario Size
    ベイク後のAPVによるディスクサイズ
  • Baking Set Size
    選択中のベイクセットに関連する全データのサイズ

プローブの配置イメージは以下の画像を参考にしてください。

デバッグ表示

APVの挙動をデバッグするための各種機能について紹介します。

Scene View

SceneViewの上部にGIのデバッグ機能があります。

デバッグボタンを押すと以下の画像のようなメニューが出てきますが、APVの場合に使用する機能のみ紹介します。
この中でもAPVで使用するのは以下の3つで残りの項目はLightmap用のものになります。


まず次の画像はライティング表示のScene Viewになります。
これを元にそれぞれの設定がどのように動作するかを紹介します。

Contributors / Receivers


GI設定を可視化し、どのメッシュがどのベイク設定になっているかを一目で確認できます。

APVに反映されるstaticメッシュ
ライトマップと同じく動かす場合は再ベイクが必要です
ライトマップに反映されるstaticメッシュ
Rendererの初期値はLightmapに焼き込まれるので意図的か注意が必要です
オレンジ リアルタイムでAPVが反映されるメッシュ
GIに対して影響させないためので動かしたり非表示にすることが可能です
Albedo


ベイクに使用される拡散反射率のマップです。
画像の通り、Lightmap Resolutionに基づいたAlbedoになります。

Emission


ベイクに使用される発光色のマップです。

Rendering Debugger

SceneViewDebugの項目の一番下にあるRendering Debuggerから描画に関連するデバッグが可能です。
APV自体のデバッグはRendering Debuggerから「Probe Volumes」を選択します。
設定項目は多いですがよく使用するのは一部です。

Display Cells


緑色の箱1つ1つがCellという扱いでプローブ管理の最大ブロックになっています。
これは基本的にはAPVのカバー範囲を確認するための設定です。
Cellの詳細は以下に記載しています。
ベイクサイズの決定方法

Display Bricks


APVの処理単位をワイヤーフレームで表示したものになります。
大きさ毎に色分けがされており紫が最小、そこから水色、オレンジと順にレベルが上がり、この箱の数が少なければ少ないほどデータサイズが小さくなります。
Brickの詳細は以下に記載しています。
ベイクサイズの決定方法

Debug Draw Distance

Brickの表示を遠景まで写したい場合は数字を上げます。
ただしSceneViewの描画負荷が上がるのと、見にくくなるため必要な場合のみ上げた方が良さそうです。

Display Probes

実際に使用されている個々のプローブ情報を表示します。
最も影響の大きい設定項目です。

  • Probe Shading Mode
    最終的なGI情報(SH)を確認するために使用します。他にも項目はありますが、例えばValidityに切り替えるとプローブが正しく使用されているかも確認できます。
  • Debug Size
    プローブ表示のサイズを変更します。
  • Exposure Compensation
    プローブに対する露光調整を行います。(描画内容そのものには影響しません)
  • Max Subdivisions Displayed
    プローブ表示をする最大Brickレベルを指定します。
  • Min Subdivisions Displayed
    プローブ表示をする最小Brickレベルを指定します。

光漏れの軽減

APVでは、等間隔の格子状に配置されたプローブが原因で、光や影が壁を透過して漏れることがあります。この光漏れは、特に「壁の厚さがプローブ間隔より薄い場合」に発生しやすいです。

公式でもさまざまな解決策が提示されています。英語ですがGoogle翻訳で読むことが可能です。
docs.unity3d.com

マニュアルにも解決策が書かれていますが、よりわかりやすいシーンで確認してみます。
以下の画像は、天井に1つのベイクライトを配置したシンプルなシーンをライトマップ、APVそれぞれでベイクした際の結果です。
左側はライトマップを使用した正しい見た目、右側はAPVでの光漏れが発生している状態です。

ライトマップ
Adaptive Probe Volume

右側のAPV結果では、壁にめり込んだプローブが原因で黒い影がはみ出しています。また、プローブ間隔を1mに設定しているため、天井の光はほとんど反映されていません。

Dilation

プローブ拡張(Dilation)は、無効なプローブを補完し、近隣の有効なプローブからライティングデータを取得する機能です。この設定を有効にすると、光漏れが大幅に軽減されます。
これはベイク時に計算を行うので実行時の負荷に影響はありません。
設定項目は以下のとおりです。

  • Search Radius
    無効なプローブから有効なプローブまでどのくらいの距離を検索するか。初期値の1m程度で良さそうです。
  • Validity Threshold
    プローブを無効と判断するバックフェースの割合。(その面がどれだけ裏向きであるか)初期値の0.75から変えないほうが良さそうです。
  • Dilation Iterations
    Dilation計算を繰り返す回数を設定します。初期値は1回ですが、2回以上に増やすと改善が見られます。体感はできていないですがおそらくベイク負荷が上がります。
  • Squared Distance Weighting
    距離計算の方式。チェックをつければ大丈夫です。

Dilationを適用した結果が以下の画像になります。
先ほどまであった黒い影がほぼ解決していることがわかると思います。

Virtual Offset

仮想オフセット(Virtual Offset)はプローブの有効性を計算し、位置を仮想的に調整することで有効なプローブ計算を行う機能です。
この機能もベイク時に計算を行うので実行時の負荷に影響ありません。
設定項目は以下のとおりです。

  • Validity Threshold
    バックフェース割合に基づいてプローブを無効化する閾値を設定します。初期値の0.75から変えないほうが良さそうです。
  • Search Distance Multiplier
    URP が有効なプローブ位置を検索する際のために使用するレイの長さを設定します。値が高いとジオメトリを貫通するらしいので変更しない方が良さそうです。
  • Geometry Bias
    レイがジオメトリに当たった後どの程度押し出すか。初期値の0.01で問題なさそうです。
  • Ray Origin Bias
    プローブの中心と、URP が各サンプリング レイの原点として使用するポイント間の距離を設定します。初期値の-0.001から変更しないほうが良さそうです。
  • Layer Mask
    Virtual Offsetの計算に使用するレイヤーを指定します。
  • Refresh Virtual Offset Debug
    全体をベイクせずにVirtual Offsetの結果だけ確認したい場合のボタン。

以下の画像はVirtualOffsetのみオンにした状態でベイクしたものになります
陰影が滑らかになる特徴があります

Dilation + Virtual Offset

2つの機能をオンにした場合の結果が以下になります。組み合わせることでより滑らかな結果を得ることができました。

改善前
改善後

改めてライトマップと比較したものが以下になります。
Min Probe Spacingが1mなため、天井の光源は写っていないですがそれ以外はかなり再現できているのではないでしょうか?
とはいえ光漏れを確実に解決することは不可能なのでそういった場所のみライトマップを併用するのが現状取れる1番の解決策かと思っています。

ライトマップ
Adaptive Probe Volume

Probe Adjustment Volume

これは特定のプローブ設定を一部手動で調整するためのコンポーネントです。この手法は細かい制御が可能ですが、大量のプローブを扱う場合の作業負荷が高くなります。
試しに触ってみると調整にキリがないように感じたので、あくまでも最終手段として使用した方が良さそうです。

詳細は公式リファレンスをご覧ください
docs.unity3d.com

ベイクサイズの最適化

ここまではAPVの基本的な使い方を紹介しましたが、この項では実際にベイクされるベイクサイズの最適化を行います。

以下の画像は先ほど使用したシーンと同じで10m x 10mのメッシュの上にいくつかBoxを配置し、天井に1つポイントライトを配置したシンプルなものになります。


この環境のBaking Set Sizeは 4.3MBです

ベイクサイズの決定方法

APVのベイクサイズは Probeの数、Brickの数で決定します

Brickの最大単位は Cell と呼ばれ、この単位でデータが管理およびストリーミングされます。以下はその具体例です。
下の画像はRenderingDebuggerからBrickを可視化したものです。
緑色のボックスがCellに相当し、XYZ軸それぞれ2個あるので合計8個存在しています。
この内側に等間隔にプローブが格納されています。

Brick, Cellを可視化

BrickのサイズはMax Probe Spacingによって決まります。
Brickというのは、4点x4点x4点の64点プローブが存在しています。そしてプローブ間の距離が27mなので以下の画像の場合は27mのBrickということになります。

27m x 27m x 27mのCubeをBrickに合わせた

27mを64点に分割したBrickを生成するとプローブ間隔は9m
9mを64点に分割したBrickを生成するとプローブ間隔は3m
3mを64点に分割したBrickを生成するとプローブ間隔は1mになります。

つまり、Min Probe Spacingを何回3倍したサイズで生成するかというのがMax Probe Spacingです。このBrickの数をいかに減らすかがベイクサイズの削減になります。
このシーンに存在する最小Brickは 単純計算すると8 x 27 x 27 x 27 x 27 = 4,251,528個になります。
そしてそのBrickには64個のProbeを格納しているのでとんでもない数になってしまいます。(内部的に最適化されていると思うので単純にこの数にはならないと思います)

そこでUnityはBrickをメッシュが存在している箇所のみ生成します。

Fill Empty Spacesにチェックを入れてOverride Probe Spacingを1mに制限することでメッシュが存在しない箇所も全て生成可能です

まずわかりやすいようにBrickのデバッグ表示だけに絞ったものが以下の画像です。

右下のOverlayでProbeの距離が表示されています

これだけでもなんとなく伝わると思いますが、実際のメッシュは中央にしかないのでオレンジ色のBrickはほとんど生成されていません。

オレンジBrickに近づいてみる
最小単位の紫Brickまで近づく

これらを見ていただくとメッシュが存在しているBrickのみ生成されていることがわかると思います。これにより4MBという小さい値でベイクできていた訳です。

ベイクサイズの削減方法

APVの仕様がなんとなく分かったところでベイクサイズの削減を行ってみます。

Max Probe Spacingの調整

Max Probe Spacingは、プローブ配置の最大間隔を指定するパラメータです。この値を適切に設定することで不要なプローブを削減します。

メッシュに対して最大Brickサイズが大きいのでMax Probe Spacingを27mから9mにしてみます。

Max 27m 4.3MB
Max 9m 4.3MB

ベイクサイズは4.3MBから4.3MBとなり変わりません…

削減されたのがメッシュが存在しない領域なのでおそらく変わらなかったのだと思います。(これは謎です)
どちらにしてもMax Probe Spacingは不要であれば下げるに越したことはなさそうです。

Probe Offsetの調整

Probe Offsetを使用してプローブの配置を適切に調整することで、効率的なCell配置をすることができます。
先ほどのベイクではCell(緑グリッド)が8個あるのが気になるのでProbeOffsetで1個になるようにずらしてみます。

Max Probe Spacingが9mの場合、緑のCellは1辺27mになります。
そこでCellの中心点が原点に来るように13.5mオフセットしてみます。

Max 9m 4.3MB (8Cells)
Max 9m 0.5MB (1Cell)

上記の結果、Cell数が8つから1つに減少。ファイルサイズは4.3MBから0.5MBに大幅に削減されました。
Brickを見ると無駄なく治っていることが分かります。

今回のメッシュは10m x 10mなので半分Cellサイズが半分でも入りそうです。
そこで今度はMin Probe Spacingを0.5mにしてみます。 Probe Offsetも半分の (6.75, 6.85, 6.75)になります。

Max 4.5m 1.1MB

1辺13.5mのBoxになりました。
密度は1m立方体が0.5m立方体になったので単純なプローブ密度は8倍ですが、サイズは2倍ほどの増加で抑えられました。
このようにBrick数を意識してMax Probe SpacingとProbe Offsetを指定することで大幅な削減が可能です。
最終的にある程度自動化したいですが、これらの挙動を意識していただくとより最適なデータを作成することが可能かと思います。

まとめ

APVの設定で特に重要なポイントは、

  • Min / Max Probe Spacing の適切な設定
  • Probe Offset の活用
  • LayerMask を活用した無駄の削減

になります。

APVを単独で使用すると特定条件下での描写に限界があります。そこでライトマップとの併用をすることでより、効率の良い照明効果を実現可能になるかと思います。小物はAPV、大きな構造物(床や壁)はライトマップという使い分けがいいのではないかと現状は考えています。

APVに関連する設定と挙動を一通り紹介しました。
今後のUnityアップデートでまた仕様追加されたりするかもしれませんが、プローブの概念を理解しておくとデザイナーの方も効率のいい配置ができるのではないかと思います。