はじめに
https://unity.com/ja/features/2dtools
Unityでは2D専用のライティングシステム(2D Renderer)が用意されています。
この専用パイプラインを用いずに、通常のURP(Forward Rendering)でもスプライトをライティングさせることも可能ですが、ライティングの際に特定の状況でバグが生じたため、その再現と解決法を解説します。
環境
・Unity(2020.3.24f)
・URP10.9.0
セッティング
SpriteRendererの設定
適当なGameObjectを作成しSpriteRendererコンポーネントを追加します。
右上の三点が連なった部分をクリックしてデバッグを選択し、SpriteRendererの投影と影を受けるをチェックします。スプライトでも影の生成、影を受けることができるようになりました。
Shaderを作成
次に適当なShaderを作成してプロパティにテクスチャを追加します。Referenceに_MainTexを設定することでスプライトの画像をマテリアルが受け取れるようになります。
Use Alpha ClipとTwo Slide
・Alphaを透過するためにUse Alpha Clipをオン
・両面を描画するためにTwo Slideをオン
デフォルトのSpriteRendererが用いるマテリアルはRenderQueueがTransparent(不透明)に設定されているためAlpha Blendを行うことができますが、今回はスプライトを不透明描画(Opaque)で描画したいため、AlphaClipをオンにして透過させます。
出力のAlphaの値にテクスチャのAチャンネルを接続します。
RenderQueueの詳細な説明は省きます。ドキュメント等々を参照してください。
https://docs.unity3d.com/ja/2018.4/ScriptReference/Rendering.RenderQueue.html
ライティング
ライティングを行います。左右反転したい場合はSprite Rendererの反転ボックスをオンにしてください。問題なくライティングを行うことができます。
バグと原因
この方法では以下の状況で正常にライティングが行えません。
・オブジェクトを回転させ裏面をライティングする
・スプライトのスケールを-1に設定してをライティングする
左側が回転を行っていない状態、右側がY軸周りに回転させた状態です。
ライティング結果が異なることが分かります。
上記のような状況では裏面描画の際のノーマル値、タンジェント値、バイタンジェント値が若干弱いです。接空間自体が裏表で異なるようです。ノーマル値はShaderGraph内で修正することができますが、タンジェント値、バイタンジェント値は変更することができないのでShader Graph内の操作のみで完結する根本的な解決策はありません。
一時的な解決策
ライティング方法を変更する
一時的な解決策としてはLit Shaderのライティング処理を切って独自のライティングを行うことです。
WorkflowをSpecularに設定してBase ColorやSpecular Colorを真っ黒にすることでライティングの影響は受けない状態になります。ライティングの出力結果をEmissionとして出力すればPBRのライト結果を無効にした状態でカスタムライティングを行うことができます。
カスタムライティングはUnityの公式チュートリアルを参考にしてください。
https://blog.unity.com/ja/technology/custom-lighting-in-shader-graph-expanding-your-graphs-in-2019
Unlit Shaderを用いてもライティング処理は行えますが、Unlit Shaderではメインライト(Direction Light)やサブライト(Spot Light)のシャドウを受け取れないため注意してください。
終わりに
Unityの意図していない方法でグラフィックス処理を行うと度々問題に衝突します。URPの機能自体もバージョンごとに若干異なるので移行も大変なので、基本的な機能は安定してほしいなぁという感想です。