GameTech/URP 渲染实战
源码 / shaders/Ch06/CascadeDebug.glsl
shaders/Ch06/CascadeDebug.glsl
// 案例 6.6 级联阴影可视化:按像素所在的级联染色(GLSL 版,对应 Ch06/CascadeDebug.shader)
// 级联包围球 _CascadeShadowSplitSpheres0~3 由引擎按 Asset 的级联数、分割比例和阴影距离算好(与 URP 同名)。
Shader "Cookbook/Ch06/CascadeDebug"
{
    SubShader
    {
        Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" "Queue"="Geometry" }

        GLSLINCLUDE
        uniform vec4  _BaseMap_ST;
        uniform vec4  _BaseColor;
        uniform float _TintStrength;
        ENDGLSL

        Pass
        {
            Name "ForwardLit"
            Tags { "LightMode"="UniversalForward" }

            GLSLPROGRAM
            uniform sampler2D _BaseMap;

            VARYING vec2 uv;
            VARYING vec3 positionWS;
            VARYING vec3 normalWS;

            #ifdef VERTEX
            void main()
            {
                VertexPositionInputs pos = GetVertexPositionInputs(positionOS.xyz);
                gl_Position = pos.positionCS;
                positionWS = pos.positionWS;
                normalWS = TransformObjectToWorldNormal(normalOS);
                uv = TransformTex(texcoord0.xy, _BaseMap_ST);
            }
            #endif

            #ifdef FRAGMENT
            void main()
            {
                vec3 albedo = texture(_BaseMap, uv).rgb * _BaseColor.rgb;
                vec3 N = normalize(normalWS);

                Light mainLight = GetMainLight(TransformWorldToShadowCoord(positionWS));
                vec3 color = albedo * mainLight.color * mainLight.shadowAttenuation * saturate(dot(N, mainLight.direction));
                color += albedo * SampleSH(N) * 0.4;

                // ComputeCascadeIndex:依次判断像素是否落在 4 个“级联包围球”里,返回第一个命中的序号;
                // 4 表示超出了所有级联(阴影距离之外)。
                // HLSL 版用 _MAIN_LIGHT_SHADOWS_CASCADE 关键字区分;GLSL 版里它是 uniform:_MainLightShadowsCascade > 0.5
                float cascade = 0.0;   // 只有一个级联时 URP 不会更新包围球数据,直接当作第 0 级
                if (_MainLightShadowsCascade > 0.5) cascade = ComputeCascadeIndex(positionWS);

                const vec3 kCascadeColors[5] = vec3[5](
                    vec3(1.0, 0.25, 0.2), vec3(0.25, 0.85, 0.3), vec3(0.25, 0.45, 1.0), vec3(1.0, 0.85, 0.2), vec3(1, 1, 1)
                );
                vec3 tint = kCascadeColors[int(cascade)];
                color = mix(color, color * tint * 1.6, _TintStrength);
                fragColor = vec4(color, 1.0);
            }
            #endif
            ENDGLSL
        }

        // ---- 投影与深度:见案例 6.4 与 6.8 ----
        Pass
        {
            Name "ShadowCaster"
            Tags { "LightMode"="ShadowCaster" }
            ZWrite On
            ZTest LEqual
            ColorMask 0

            GLSLPROGRAM
            #include "Ch06/ShadowCasterPass.glsl"
            ENDGLSL
        }

        Pass
        {
            Name "DepthOnly"
            Tags { "LightMode"="DepthOnly" }
            ZWrite On
            ColorMask R

            GLSLPROGRAM
            #include "Ch06/DepthOnlyPass.glsl"
            ENDGLSL
        }
    }
}