読者です 読者をやめる 読者になる 読者になる

テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】リアルタイムな影とベイクした影を混ぜる、Shadow Mask 特集号

f:id:tsubaki_t1:20170418215930j:plain

今回はUnity 5.6で追加されたLightingの新しい機能、特にShadowmaskについてです。

Shadow Maskは動的な影と静的な影を混ぜる手法

まずShadowMaskとは何ぞやという話ですが、要するに動的な影と静的な影を混ぜる新しい手法の一つです。

f:id:tsubaki_t1:20170418221250j:plain

tsubakit1.hateblo.jp

今までMixed系の手法は、ライトマップに焼いた部分は(既に焼いた)ライトの影響を受けず、ダイナミックなオブジェクトのみ影を描画する…という手法でした。
その場合、既に焼いたライトマップに追加でライトが加算描画されるといった事が発生していました。例えば下の場合、赤が動的、青が静的な影です。赤の落とす影が一部濃くなって描画されています。

f:id:tsubaki_t1:20170418223021j:plain

5.6以前でも回避方法は無い訳ではありませんでしたが、5.6のShadow Maskでより綺麗かつシンプルに回避が可能になりました。

下の図ではShadow Maskを使用しています。

f:id:tsubaki_t1:20170418223635j:plain

「影」の計算を事前に行う

ShadowMaskのやっている事は単純で、影を事前に計算しておく事です。
下ではほぼ全てのモデルがリアルタイムな影を持つ場合です。FrameDebuggerで確認すると、Shadows.RenderJobDirで影の計算が行われている事が確認出来ます。

f:id:tsubaki_t1:20170418231014j:plain

ソレに対してShadowMaskで影を生成してみます。今度は赤はDynamic、青はStaticである場合です。
シーンは同じですが、Shadow.RenderJobDirで生成している影のテクスチャには、ダイナミックな赤い球しか表示されなくなりました。
ソレ以外の影は事前にShadowMaskとして計上されています。

f:id:tsubaki_t1:20170418231957j:plain

マスクなので輝度や色を変える事が出来る

Shadow Maskを色々試して気づいた面白い事の一つは、今までのBaked Shadowと異なり輝度や色を変更出来る点です。

f:id:tsubaki_t1:20170418225151j:plain

このミソはShadowMaskはあくまでもマスクであるという点です。

今までは影はベイクするとテクスチャに全て書き込んでいました。そのためテクスチャ自体の色を変えない限り影の色や輝度を変更する事は出来ませんでした。

 

ShadowMaskは単純に「マスク」で、影計算は事前に行いますが光の計算はリアルタイムに行うので、光の色や輝度を変更しても反映する事が出来る訳です。

f:id:tsubaki_t1:20170418225555j:plain

ただし、下にも書きましたが間接光の計算は確定しているので、あまり強力に色を変えたりしない方が良さそうです。少し点滅するくらい。

間接光は事前にテクスチャに焼かれる

影以外の光の計算がリアルタイムで行われるとなったとき気になるのは間接光の扱いですが、事前計算してテクスチャに焼きこまれます。

f:id:tsubaki_t1:20170418232740j:plain

上の内容で「RealtimeGIを設定しとけばGIが更新できる」ようにTwetterで書いてますが、これは自分の勘違いです。
テクスチャにベイクされるので更新出来ません。

光沢が綺麗に出る

Shadow Maskは影の設定だけで光はリアルタイムです。なので光沢もリアルタイムと同じように出ます。

Unity 5.5以前はライトマップにベイクしてしまうと光沢が死ぬ問題がありましたが、ShadowMaskを使えば光沢が表現されます。

下は青がStatic(+Shadow Mask)、赤がリアルタイムです。

f:id:tsubaki_t1:20170419005101j:plain

tsubakit1.hateblo.jp

 Cookieが使える

ShadowMaskは光計算はリアルタイムなので、クッキーが使えます。

f:id:tsubaki_t1:20170419010614j:plain

クッキーで絞り込んでいる場合でも、ShadowMaskは最大範囲で作られるので、少し動かしたり出来るのは若干面白いです。

f:id:tsubaki_t1:20170419011211g:plain

近距離はダイナミックに、遠距離はShadowMaskを使う

個人的に最も気に入っている機能はDistance Shadowmaskの機能です。

この機能では「遠距離の影はShadowMaskを使うが近距離の影はダイナミックに描画する」という機能です。

何が良いかと言えば単純に、影の解像度を減らせます。

f:id:tsubaki_t1:20170418234112j:plain

遠距離に低解像度のShadowMaskを使って、色々と節約

例えば下のシーンでは、17mのリアルタイムシャドウでソレ以外はShadowMaskを使用しています。一見それなりに見えますし、実際近くの影は綺麗に描画出来ています。

f:id:tsubaki_t1:20170418235557j:plain

ShadowMapの解像度を節約

実はここで使用しているShadowMaskは、実はShadowMaskのResolutionは「5」という恐ろしく低い値を設定しています

この解像度でShadowMaskを表示するとボケボケの影が表示される事になりますが、近距離はダイナミックに影を描画する事で、近距離はパッキリと遠距離はボケボケの影が使用できます。

f:id:tsubaki_t1:20170419000059j:plain

これが生むメリットの一つは、Lightmapのサイズです。徹底して低解像度に出来るので、サイズを大きく下げる事が出来ます。

例えば上のシーンに使用しているマップは50*20m級のマップですが、ここで使用しているテクスチャのサイズはたったの341kbに収まります。

これをDistance Shadowを使用せず綺麗な影のライトマップを表現しようとResolution 40(初期値)でやろうと思ったら、11MB近くになり、沢山のメモリと高いロードのコストを払う事になります。

f:id:tsubaki_t1:20170419001248j:plain

またベイクのための解像度が減る事で、ライトマップが少し早く焼けます。

 

なお、Lightmapの解像度を下げるとShadowMaskの解像度だけでなく、間接光の解像度やEmissiveなオブジェクトの解像度、Bakedでテクスチャに焼き込んだ影の品質が下がります。
下の図はResolution2で影をベイクした場合です。staticが近距離では汚く見えます。

f:id:tsubaki_t1:20170419020209j:plain

 リアルタイムな影の負荷を節約 or 高品質化

何より良いのは、手前側のリアルタイムな影の品質も向上する事です。
影に使用するテクスチャは、影の品質で設定したサイズをShadow Distanceで分割していきます。その為、影の描画範囲が狭ければ狭い程、高解像度な影が描画出来ます。

f:id:tsubaki_t1:20170419002354j:plain

もし右のようなフワっとした影が好みなら、ShadowのResolutionを落とせば良いです。それで(Soft Shadowなら)フワっとなりますし、描画負荷も落ちます。

影がShadowMaskになるタイミングは、Cascadeで見ると良いです。

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

2017と5.6でDistance Shadowの設定位置が異なる

まだ確定かは分かりませんが、Unity 2017では設定位置が変化していました。

tsubakit1.hateblo.jp

Shadow Maskの使い方

LightingのLighting ModeをShadowmaskに設定し、ShadowMaskを作りたいライトをMixedに設定するだけです。

f:id:tsubaki_t1:20170419014227j:plain

tsubakit1.hateblo.jp

関連

tsubakit1.hateblo.jp