Unity URP 2D Light セッティングあれこれ 

Unity URP 2D Light の設定について、毎回忘れてしまうので自分用覚書です。
<iframe width="560" height="315" src="https://www.youtube.com/embed/w6c5xj-0Nv0?si=fmr5Tr17onkCElBq" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

* Project Settings > Graphics Default Render Pipeline を URP-2D のものにする 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/85941e4b-191c-4fc4-b4f7-137fb48b1434.png)

* Create > Light > * 2D系のライトを使用する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/a8f692a0-d8b3-4edc-90f2-0a72c6e25014.png)

* LightのBlending,Shadows,NormalMapを設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/5a34ba62-fd9f-44f7-80d3-167056ff81a9.png)

* ライトおよびマスク用のライト（リムライト）を用意し、適宜設定する
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/587a4d7a-5452-45e2-81dc-3a6831dfe4ce.png)

* スプライトに使用するシェーダーを URP > 2D > Sprite-Lit-Defaultにする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/49afabf5-6d33-462d-bdb4-7c2138ca0541.png)

* Sprite > Open Sprite Editor > 左上 > Secondaly Textures に _NormalMap と _MaskMap を追加する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/b3dd484d-86f8-4bd6-adea-5db657f33c88.png)


* CompositeShadowCaster2D をアタッチしたGameObjectの下にスプライト群を置くと影が統合される

| 統合前 | 統合後 |
|:-:|:-:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/c1f5ab29-a1ba-413b-987f-807d043780a4.png" width=300px> | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/f2b4e42d-fb40-45b8-b1a7-d76ea5c86f24.png" width=300px>|



**おまけ**
normalの反転/強度を変更できるようにしたSprite-Lit-Default
| 効果小 | 効果大 |
|:-:|:-:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/b3023011-c920-4ef2-ba26-d5738b81f194.png" width=300px> | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/139174c5-bf1b-4f96-9731-539a60619899.png" width=300px>|

<details><summary>ソースコード(Unity6)</summary>

```
Shader "Universal Render Pipeline/2D/Sprite-Lit-DefaultEx(Unity6)"
{
    Properties
    {
        _MainTex("Diffuse", 2D) = "white" {}
        _MaskTex("Mask", 2D) = "white" {}
        _NormalMap("Normal Map", 2D) = "bump" {}
        _NormalIntensity("Normal Intensity", Range(-2,2)) = 1
        _ZWrite("ZWrite", Float) = 0

        // Legacy properties. They're here so that materials using this shader can gracefully fallback to the legacy sprite shader.
        [HideInInspector] _Color("Tint", Color) = (1,1,1,1)
        [HideInInspector] _RendererColor("RendererColor", Color) = (1,1,1,1)
        [HideInInspector] _AlphaTex("External Alpha", 2D) = "white" {}
        [HideInInspector] _EnableExternalAlpha("Enable External Alpha", Float) = 0
    }

    SubShader
    {
        Tags {"Queue" = "Transparent" "RenderType" = "Transparent" "RenderPipeline" = "UniversalPipeline" }

        Blend SrcAlpha OneMinusSrcAlpha, One OneMinusSrcAlpha
        Cull Off
        ZWrite [_ZWrite]
        ZTest Off

        Pass
        {
            Tags { "LightMode" = "Universal2D" }

            HLSLPROGRAM
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/Core2D.hlsl"

            #pragma vertex CombinedShapeLightVertex
            #pragma fragment CombinedShapeLightFragment

            #include_with_pragmas "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/ShapeLightShared.hlsl"

            #pragma multi_compile _ DEBUG_DISPLAY SKINNED_SPRITE

            struct Attributes
            {
                float3 positionOS   : POSITION;
                float4 color        : COLOR;
                float2 uv           : TEXCOORD0;
                UNITY_SKINNED_VERTEX_INPUTS
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float4  positionCS  : SV_POSITION;
                half4   color       : COLOR;
                float2  uv          : TEXCOORD0;
                half2   lightingUV  : TEXCOORD1;
                #if defined(DEBUG_DISPLAY)
                float3  positionWS  : TEXCOORD2;
                #endif
                UNITY_VERTEX_OUTPUT_STEREO
            };

            #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/LightingUtility.hlsl"
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/DebugMipmapStreamingMacros.hlsl"

            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);
            UNITY_TEXTURE_STREAMING_DEBUG_VARS_FOR_TEX(_MainTex);

            TEXTURE2D(_MaskTex);
            SAMPLER(sampler_MaskTex);

            // NOTE: Do not ifdef the properties here as SRP batcher can not handle different layouts.
            CBUFFER_START(UnityPerMaterial)
                half4 _Color;
            CBUFFER_END

            #if USE_SHAPE_LIGHT_TYPE_0
            SHAPE_LIGHT(0)
            #endif

            #if USE_SHAPE_LIGHT_TYPE_1
            SHAPE_LIGHT(1)
            #endif

            #if USE_SHAPE_LIGHT_TYPE_2
            SHAPE_LIGHT(2)
            #endif

            #if USE_SHAPE_LIGHT_TYPE_3
            SHAPE_LIGHT(3)
            #endif

            Varyings CombinedShapeLightVertex(Attributes v)
            {
                Varyings o = (Varyings)0;
                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                UNITY_SKINNED_VERTEX_COMPUTE(v);

                v.positionOS = UnityFlipSprite(v.positionOS, unity_SpriteProps.xy);
                o.positionCS = TransformObjectToHClip(v.positionOS);
                #if defined(DEBUG_DISPLAY)
                o.positionWS = TransformObjectToWorld(v.positionOS);
                #endif
                o.uv = v.uv;
                o.lightingUV = half2(ComputeScreenPos(o.positionCS / o.positionCS.w).xy);

                o.color = v.color * _Color * unity_SpriteColor;
                return o;
            }

            #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/CombinedShapeLightShared.hlsl"

            half4 CombinedShapeLightFragment(Varyings i) : SV_Target
            {
                const half4 main = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
                const half4 mask = SAMPLE_TEXTURE2D(_MaskTex, sampler_MaskTex, i.uv);
                SurfaceData2D surfaceData;
                InputData2D inputData;

                InitializeSurfaceData(main.rgb, main.a, mask, surfaceData);
                InitializeInputData(i.uv, i.lightingUV, inputData);

                SETUP_DEBUG_TEXTURE_DATA_2D_NO_TS(inputData, i.positionWS, i.positionCS, _MainTex);

                return CombinedShapeLightShared(surfaceData, inputData);
            }
            ENDHLSL
        }

        Pass
        {
            ZWrite Off

            Tags { "LightMode" = "NormalsRendering"}

            HLSLPROGRAM
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/Core2D.hlsl"

            #pragma vertex NormalsRenderingVertex
            #pragma fragment NormalsRenderingFragment

            #pragma multi_compile _ SKINNED_SPRITE

            struct Attributes
            {
                float3 positionOS   : POSITION;
                float4 color        : COLOR;
                float2 uv           : TEXCOORD0;
                float4 tangent      : TANGENT;
                UNITY_SKINNED_VERTEX_INPUTS
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float4  positionCS      : SV_POSITION;
                half4   color           : COLOR;
                float2  uv              : TEXCOORD0;
                half4   normalWS        : TEXCOORD1;
                half3   tangentWS       : TEXCOORD2;
                half3   bitangentWS     : TEXCOORD3;
                UNITY_VERTEX_OUTPUT_STEREO
            };

            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);
            TEXTURE2D(_NormalMap);
            SAMPLER(sampler_NormalMap);
            half _NormalIntensity;

            // NOTE: Do not ifdef the properties here as SRP batcher can not handle different layouts.
            CBUFFER_START( UnityPerMaterial )
                half4 _Color;
            CBUFFER_END

            Varyings NormalsRenderingVertex(Attributes attributes)
            {
                Varyings o = (Varyings)0;
                UNITY_SETUP_INSTANCE_ID(attributes);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                UNITY_SKINNED_VERTEX_COMPUTE(attributes);

                attributes.positionOS = UnityFlipSprite(attributes.positionOS, unity_SpriteProps.xy);
                o.positionCS = TransformObjectToHClip(attributes.positionOS);
                o.uv = attributes.uv;
                o.color = attributes.color;
                o.normalWS.xyz = -GetViewForwardDir();
                o.normalWS.w = _NormalIntensity;
                o.tangentWS = TransformObjectToWorldDir(attributes.tangent.xyz);
                o.bitangentWS = cross(o.normalWS.xyz, o.tangentWS) * attributes.tangent.w;
                return o;
            }

            #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/NormalsRenderingShared.hlsl"

            half4 NormalsRenderingFragment(Varyings i) : SV_Target
            {
                const half4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
                half3 normalTS = UnpackNormal(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, i.uv));
                normalTS = normalize(half3(normalTS.x * i.normalWS.w, normalTS.y * i.normalWS.w, normalTS.z));
                half4 ret = NormalsRenderingShared(mainTex, normalTS, i.tangentWS.xyz, i.bitangentWS.xyz, i.normalWS.xyz);
                return ret;
            }
            ENDHLSL
        }

        Pass
        {
            Tags { "LightMode" = "UniversalForward" "Queue"="Transparent" "RenderType"="Transparent"}

            HLSLPROGRAM
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/Core2D.hlsl"
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/DebugMipmapStreamingMacros.hlsl"
            #if defined(DEBUG_DISPLAY)
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Debug/Debugging2D.hlsl"
            #endif

            #pragma vertex UnlitVertex
            #pragma fragment UnlitFragment

            #pragma multi_compile _ DEBUG_DISPLAY SKINNED_SPRITE

            struct Attributes
            {
                float3 positionOS   : POSITION;
                float4 color        : COLOR;
                float2 uv           : TEXCOORD0;
                UNITY_SKINNED_VERTEX_INPUTS
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float4  positionCS      : SV_POSITION;
                float4  color           : COLOR;
                float2  uv              : TEXCOORD0;
                #if defined(DEBUG_DISPLAY)
                float3  positionWS  : TEXCOORD2;
                #endif
                UNITY_VERTEX_OUTPUT_STEREO
            };

            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);
            UNITY_TEXTURE_STREAMING_DEBUG_VARS_FOR_TEX(_MainTex);

            // NOTE: Do not ifdef the properties here as SRP batcher can not handle different layouts.
            CBUFFER_START( UnityPerMaterial )
                half4 _Color;
            CBUFFER_END

            Varyings UnlitVertex(Attributes attributes)
            {
                Varyings o = (Varyings)0;
                UNITY_SETUP_INSTANCE_ID(attributes);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                UNITY_SKINNED_VERTEX_COMPUTE(attributes);

                attributes.positionOS = UnityFlipSprite( attributes.positionOS, unity_SpriteProps.xy);
                o.positionCS = TransformObjectToHClip(attributes.positionOS);
                #if defined(DEBUG_DISPLAY)
                o.positionWS = TransformObjectToWorld(attributes.positionOS);
                #endif
                o.uv = attributes.uv;
                o.color = attributes.color * _Color * unity_SpriteColor;
                return o;
            }

            float4 UnlitFragment(Varyings i) : SV_Target
            {
                float4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);

                #if defined(DEBUG_DISPLAY)
                SurfaceData2D surfaceData;
                InputData2D inputData;
                half4 debugColor = 0;

                InitializeSurfaceData(mainTex.rgb, mainTex.a, surfaceData);
                InitializeInputData(i.uv, inputData);
                SETUP_DEBUG_TEXTURE_DATA_2D_NO_TS(inputData, i.positionWS, i.positionCS, _MainTex);

                if(CanDebugOverrideOutputColor(surfaceData, inputData, debugColor))
                {
                    return debugColor;
                }
                #endif

                return mainTex;
            }
            ENDHLSL
        }
    }

    Fallback "Sprites/Default"
}

```
</details>

<details><summary>ソースコード(Unity2022)</summary>

```
using UnityEngine;
using UnityEngine.Rendering;

namespace ModelToBump
{
    //https://docs.unity3d.com/ja/2021.3/Manual/srp-setting-render-pipeline-asset.html
    public class ActiveRenderPipelineExample : MonoBehaviour
    {
        // In the Inspector, assign a Render Pipeline Asset to each of these fields
        public RenderPipelineAsset defaultRenderPipelineAsset;
        public RenderPipelineAsset overrideRenderPipelineAsset;

        void Start()
        {
            GraphicsSettings.defaultRenderPipeline = defaultRenderPipelineAsset;
            QualitySettings.renderPipeline = overrideRenderPipelineAsset;

            DisplayCurrentRenderPipeline();
        }

        void Update()
        {
            // When the user presses the left shift key, switch the default render pipeline
            if (Input.GetKeyDown(KeyCode.LeftShift))
            {
                SwitchDefaultRenderPipeline();
                DisplayCurrentRenderPipeline();
            }
            // When the user presses the right shift key, switch the override render pipeline
            else if (Input.GetKeyDown(KeyCode.RightShift))
            {
                SwitchOverrideRenderPipeline();
                DisplayCurrentRenderPipeline();
            }
        }

        // Switch the default render pipeline between null,
        // and the render pipeline defined in defaultRenderPipelineAsset
        void SwitchDefaultRenderPipeline()
        {
            if (GraphicsSettings.defaultRenderPipeline == defaultRenderPipelineAsset)
            {
                GraphicsSettings.defaultRenderPipeline = null;
            }
            else
            {
                GraphicsSettings.defaultRenderPipeline = defaultRenderPipelineAsset;
            }
        }

        // Switch the override render pipeline between null,
        // and the render pipeline defined in overrideRenderPipelineAsset
        void SwitchOverrideRenderPipeline()
        {
            if (QualitySettings.renderPipeline == overrideRenderPipelineAsset)
            {
                QualitySettings.renderPipeline = null;
            }
            else
            {
                QualitySettings.renderPipeline = overrideRenderPipelineAsset;
            }
        }

        // Print the current render pipeline information to the console
        void DisplayCurrentRenderPipeline()
        {
            // GraphicsSettings.defaultRenderPipeline determines the default render pipeline
            // If it is null, the default is the Built-in Render Pipeline
            if (GraphicsSettings.defaultRenderPipeline != null)
            {
                Debug.Log("The default render pipeline is defined by " + GraphicsSettings.defaultRenderPipeline.name);
            }
            else
            {
                Debug.Log("The default render pipeline is the Built-in Render Pipeline");
            }

            // QualitySettings.renderPipeline determines the override render pipeline for the current quality level
            // If it is null, no override exists for the current quality level
            if (QualitySettings.renderPipeline != null)
            {
                Debug.Log("The override render pipeline for the current quality level is defined by " + QualitySettings.renderPipeline.name);
            }
            else
            {
                Debug.Log("No override render pipeline exists for the current quality level");
            }

            // If an override render pipeline is defined, Unity uses that
            // Otherwise, it falls back to the default value
            if (QualitySettings.renderPipeline != null)
            {
                Debug.Log("The active render pipeline is the override render pipeline");
            }
            else
            {
                Debug.Log("The active render pipeline is the default render pipeline");
            }

            // To get a reference to the Render Pipeline Asset that defines the active render pipeline,
            // without knowing if it is the default or an override, use GraphicsSettings.currentRenderPipeline
            if (GraphicsSettings.currentRenderPipeline != null)
            {
                Debug.Log("The active render pipeline is defined by " + GraphicsSettings.currentRenderPipeline.name);
            }
            else
            {
                Debug.Log("The active render pipeline is the Built-in Render Pipeline");
            }
        }
    }
}
```
</details>


以上です。