前回まででAdditional Lightの実装を行いましたが、まだ影を落とすことができていませんので今回はその対応を、いわつるShadow Casterの実装を行っていきます。
前回までの記事はこちらからどうぞ
atelier-aomi.hatenablog.com
実行環境:Unity6(6000.0.26f1)
今回の目的
影を落とすためにはそれ用のPassを追加する必要があります。今回はそのPassの実装をし、Additional Lightの落ち影を出せるようにすることを目的とします。
Passについては今後執筆予定のアウトラインの実装でも必要な知識になってきます。
また、今回の内容は主にコード側がメインの話になるため、ノードの方はサクッと済ませます。というかノードの方は特に何もする必要がないです。
前提知識:Passについて
ここまでの実装は全てUniversalForwardPassというURP環境における最も一般的な描画処理の実装をしてきました。
Passについては以前にも下の記事の「SubShaderとPassについて」軽く触れているのでまずはそちらに目を通していただけると良いかなと思います。
atelier-aomi.hatenablog.com
今回の実装で言うとUniversalForwardPassというPassではシェーダーを割り当てたメッシュ自身の描画処理を行うPassになります。
一方で影を落とすというものは自身ではなくほかのモデルに対して影を落とすわけですから別途Passの実装が必要ということになります。
そのPassをShadowCasterといい、Unityが標準で用意してくれているのでそれを使用することで落ち影を実装することが出来ます。
Unity側が標準で用意してくれているパスは以下のページから確認することができます。
今回はその中のShadowCasterを使用する、という形です。
URP ShaderLab のパスタグ | Universal RP | 14.0.2
前提知識:影を落とすための事前設定
ちゃんとShadow Casterの設定したはずなんだけどなんか影が落ちない...なぜ...?
ということが自分が製作しているときもしばしばあります。
ちょっとした設定漏れが大体の原因なので先に影を落とすための設定回りに関して把握しておきます。
(ちなみに蒼水はLightの設定をやらかして影が出ず時間を無駄にしました)
Lightの設定
Directional Light

Directional LightにはShadowsという項目がありその中にShadow Typeというものがあります。
これがNo Shadowsに設定されているとそもそもライト自体が影を落とさない設定になってしまうのでまずはここを確認します。
Point Light / Spot Light

Point LightやSpot Light同様にShadowsの項目にShadow TypeがあるのでここがNo Shadowsになっていると影を落とすことができません。
実際に設定を切り替えてみると下動画のような挙動を確認できます。

3Dモデル(SkinnedMesh / Mesh Renderer)側の設定
Skinned Mesh Renderer

Skinned Mesh RendererのインスペクタのLightingの項目がありこの中にCast Shadowの設定があるのでここをOnにしておく必要があります。
Mesh Renderer

Mesh Rendererの方も同様にLightingの項目の中にCast Shadowの設定があるのでこちらをOnにしておきます。
落ちない場合ここがOffになっている場合があるのでここを確認しましょう。
実際にOn/Offを切り替えてみると下動画のような挙動を確認することができます。

Project Settingsの設定

Project Settings -> Graphics の項目にはUniversal Render Pipeline Assetというものが設定されており、このAssetの中でLightやShadowに関する設定を行うことができます。
Additional Lightは前回の記事でも触れたように数には上限があると同時に、上限数設定が少なく設定されているとそもそも処理されなくなりますのでそのあたりの設定は確認しておきましょう。
デフォルト設定で問題ないはずではありますが、何かの拍子でおかしくなっている場合もあるので前項に対応してもダメだったらこちらも見てみても良いかもしれませんね。
ノードで見るShadowCasterPass
今回は特に対応する必要はありません。
前提知識で触れた落ち影に関係する事前設定さえきちんとできていればShaderGraphは標準で影を落としてくれます。
コードで見るShadowCasterPass
コード側では今まで実装してきたUniversalForwardPassからいったん離れ新しいPassの実装を行います。
と言っても、Unityが全て用意してくれているものをそのまま使用するだけなのでそこまで難しくはありません。
どういったPassの内容になっているかだけ順を追って確認してみましょう。
Name / Tag
NameとTagは以下のように記載します。
NameとTagは今回のPassはShadowCasterPassなのでShadowCasterと記載します。
UnityはとくにこのLightModeのほうが重要で、ここの名前で処理を実行したりするのでここは正しく記載しておく必要があります。
先ほども貼りましたが以下のページにあるプロパティ名にしておく必要があります。
ちなみにこれまでの実装は一番一般的な処理になるためUniversalForwardを使用していた、ということになります。
URP ShaderLab のパスタグ | Universal RP | 14.0.2
Name "ShadowCaster" Tags { "LightMode"="ShadowCaster" }
Color Mask
Color MaskとはRGB値に対する書き込みをするかどうかをマスクできるものですが、今回は0、つまりどのチャンネルにも描きこまない、という設定がこれです。
今回描画するのはモデル自身ではなく影に必要な情報だけなので色は不要、ということで0にする感じです。
ColorMask 0
pragma / include
今回のPassで使用するVertexShaderとFragmentShaderはincludeしているShadowCasterPass.hlslの中に定義されている関数を使用するのでそれと同じにする必要があります。
そのためShadowPassVertexとShadowPassFragmentという名前になっています。
ノードベース側ではこれを暗黙的に使用していると思われますがコードベースではきちんと自分で書いてあげる必要があります。
HLSLPROGRAM #pragma vertex ShadowPassVertex #pragma fragment ShadowPassFragment #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl" ENDHLSL
とはいえShadowCasterPassってそもそも標準で定義されているのでそれをincludeしたらその中にShadowPassVertexとShadowPassFragmentがあるのでそれを実行させているだけ、という形ですね。
このShadowCasterPass.hlslの中に構造体から何から全部入っているので他に書くことはありません。なお、LitInput.hlslは一緒に入れておく必要があるようなのでこれも入れておきましょう。
余談ですがその他のPassも同様に実装することができます。その辺はまた次回に詳しく書けたらなと思います。
というわけでこの対応をすることで影が落ちるようになり下画像のようになりました!

ShadowCasterPassのコード全文はこちら
Pass { Name "ShadowCaster" Tags { "LightMode"="ShadowCaster" } ColorMask 0 HLSLPROGRAM #pragma vertex ShadowPassVertex #pragma fragment ShadowPassFragment #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl" ENDHLSL }
おわりに
これでAdditional Lightの実装が終わりました。
しいて言えばAdditional LightのToon対応とかもしても良いのですが、基本以前の考え方や処理は似たようなものになりそうなので今回シリーズでは割愛しようと思います。
さて、次回は先ほど書いた通りほかのPassの実装もこのタイミングで行っておこうと思います。
ほかのPassというとDepthOnlyPassやDepthNormalPassなどです。
ちなみに今後実装していくアウトラインとかはUnity標準ではないのでまずは先にPass関連を把握しておこう!みたいな流れにしていたりします。
複数Passの記述に慣れておいた方がおそらく理解しやすいので。