Unity小林様にライティングについてご教示頂きました
前のエントリにてUnityのライティングについて集中的に調べてみたものの、それでもなお把握しきれないことをツイートしていたら、とてもありがたいことにUnityの小林様@nyaa_toranekoにかなりご丁寧な解説ツイートをいただきまして、その一連の内容がどれも私の疑問が氷解するようなお言葉でしたので、Twitterタイムラインに流されてしまうのはもったいないので以下貼り付けさせていただき、胸に刻もうと思います。
概念的には、Baked GIは「焼き付け処理」ですので、動かないものに対して行うものです。要するに壊れたり移動したりしないプロップとか背景オブジェクト対象です。あるベイク用ライトがもたらすバウンスカラーの焼き付けと、そのライトによって落ちる影をライトマップに焼き付けて使用するのが基本です
— 小林信行 Nobuyuki Kobayashi (@nyaa_toraneko) 2018年5月23日
それに対してLight Probeは空間上で、あるライトブローブがベイク時にサンプリングしたおよそのバウンスカラーを保持するもので、をその近傍にあったり通ったりするオブジェクトにそのカラーを載せてやるのが役割です。バウンスカラーを影響させるのが目的だから、動くオブジェクトなどに適してます。
— 小林信行 Nobuyuki Kobayashi (@nyaa_toraneko) 2018年5月23日
同時にバウンスカラーを載せるだけの役割しかないので、本来ならGIによって発生するはずのアンビエントオクルージョン的な影は発生しません。もしこれらの影を追加で発生させたいのなら、ポストエフェクト側でスクリーンスペースで行います。シェーダーがライトプローブに対応しているのも必須です。
— 小林信行 Nobuyuki Kobayashi (@nyaa_toraneko) 2018年5月23日
一方Precomputed GIというのは、こちらEnlighten側の機能ですが、これは一部リアルタイムGIとして利用出来るエミッシブマテリアルがアタッチされているオブジェクトからの影響を、ベイクされているライトマップにさらに加える機能だと考えるとよいです。
— 小林信行 Nobuyuki Kobayashi (@nyaa_toraneko) 2018年5月23日
リアルタイムですから、本来ベイクされ変化しないはずのライトマップに対して、追加でバウンス光を追加することができます。注意していただきたいので、基本は以上の通りなのですが、複雑な実装をされているので、バージョンによっては思った通りに動かない可能性もあります。
— 小林信行 Nobuyuki Kobayashi (@nyaa_toraneko) 2018年5月23日
ですので基本としては、●動くキャラクターに対して影を落としたい時には、リアルタイムライトを、●動かない背景などに綺麗な影やGIによる陰影を付けたい時には、ベイクしたライトマップを、●GIの影響をキャラクターにも与えたい時には、ライトプローブを、という使い分けをするといいと思います。
— 小林信行 Nobuyuki Kobayashi (@nyaa_toraneko) 2018年5月23日
これを基本とすると、後はこの3つの組み合わせから、コレとコレを同時にするにはどうしたらいい、という疑問が出ると思います。そこでテラシュールブログを見るとその解決法が載ってます。例としては「動かないオブジェクトによってベイクされた影が、リアルタイムに落ちる影と矛盾しない?」とか。
— 小林信行 Nobuyuki Kobayashi (@nyaa_toraneko) 2018年5月23日
Precomputed GIはかなりCPUに負担をかける機能なので、あまり使わないほうがいいですよ、ということも覚えておいていただけるとよいかと。
— 小林信行 Nobuyuki Kobayashi (@nyaa_toraneko) 2018年5月23日
今後ともよろしくお願いします。
このようにコメントをいただき、自分なりに以下のように咀嚼して理解させていただきました。(それでも間違っていたら恥ずかしいですが)
case1: Baked GI + Light Probe
シーン空間を動かないStaticなオブジェクトはBaked GI、動くキャラクター等の非StaticなオブジェクトはLightProbeを利用することで間接光を反映できる。ランタイム負荷のことも考慮すると、だいたいはこの設定で済ませば良い。
この場合、影については、非Staticオブジェクトはリアルタイムライトを活用する。Staticオブジェクトはベイクした綺麗な影を使うこともできるし、非Staticオブジェクトとの影のなじみを考えるのであれば、Distance Shadowmapを活用して、近場はリアルタイムな影をメインに利用し、遠景はベイクした影を利用するというアプローチもある。
※下のcase2と異なり、このcase1の場合は、小さいオブジェクトであろうが「動かないもの」はStatic設定してBaked GI対象にしてしまうのが陰影表現を考慮すると常套手段だとは思うが、いくつかのチュートリアル記事では、静的ライトマップ画像において、小物に無駄な面積を使うのを避けるために、このライト構成でも小物はBake対象外にしてLightProbe対象にしている事例もあり、判断が分かれるところなのだと思う。
case2: Baked GI + Realtime GI + Light Probe
シーン内にエミッシブなオブジェクトがあり、その光をStaticオブジェクトに反映させたい時はPrecomputed Realtime GIにチェックを入れる。
これによってBaked GI対象だったStaticオブジェクトにRealtime GIが重ね掛けされる。Realtime GIは実行時に低解像度ライトマップを生成し続ける仕様であるため、ランタイムCPU負荷は大きくなってしまう。そのため、Staticオブジェクトのうち、自身の反射光を無視できるぐらいの小さいオブジェクトは、Staticから非StaticにしてLight Probeの対象に切り替えると、Realtime GIで生成されるチャート数が減り、結果CPU負荷を下げることができる。
※個人的にはエミッシブの影響を反映するためにランタイム時のCPU負荷を上げるのは敬遠したいので、それならエミッシブなものと同じ場所に別光源を置くことでBaked GIのみで済ませたいと思う。
case3: Realtime GI + Light Probe
余談として、UnityのLightingパネルではRealtime GIにチェックを入れて、Baked GIをオフにすることもできるが、これは全く現実的な設定ではないと思う。
追記:この設定も有用らしい。Unityが最近公開したチュートリアルのシーンはこの設定で設計されている。(Deferred設定なのでVRChatで同じことができるとは言えないが)
ライトマップのベイクをしないため、開発時のイテレーションに有利に働く。
用語
- バウンス光 = 間接光 = Indirect Lighting
- Precomputed Realtime GI = Realtime GI
- Static = 静的 : ライティングに関しては、最低限Lightmap Staticにチェックが入っていること
- 非Static = Dynamic = 動的
ここまで把握できれば、あとは都度テラシュールブログ様を参考にすることで、何とかライティングしていけそうに思います。
小林様、誠にありがとうございました。