GameTech/URP 渲染实战
源码 / shaders/Ch23/ContactShadowLit.glsl
shaders/Ch23/ContactShadowLit.glsl
// 案例 23.9:接收接触阴影的简单光照 Shader(GLSL 版)。
// 阴影 = min(阴影贴图结果, 接触阴影结果):远处的大阴影交给 Shadow Map,脚底的细节交给接触阴影。
Shader "Cookbook/Ch23/ContactShadowLit"
{
    SubShader
    {
        Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" "Queue"="Geometry" }
        GLSLINCLUDE
        uniform vec4  _BaseMap_ST;
        uniform vec4  _BaseColor;
        uniform float _UseContact;
        uniform float _ShowContact;
        ENDGLSL

        Pass
        {
            Name "ForwardLit"
            Tags { "LightMode"="UniversalForward" }
            GLSLPROGRAM
            uniform sampler2D _BaseMap;
            uniform sampler2D _ContactShadowTexture;   // 由 ContactShadowFeature 设成全局纹理

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

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

            #ifdef FRAGMENT
            vec4 frag()
            {
                vec3 albedo = texture(_BaseMap, uv).rgb * _BaseColor.rgb;
                vec3 n = normalize(normalWS);
                Light l = GetMainLight(TransformWorldToShadowCoord(positionWS), positionWS, vec4(1, 1, 1, 1));

                float contact = 1.0;
                if (_UseContact > 0.5)
                {
                    vec2 screenUV = GetNormalizedScreenSpaceUV(gl_FragCoord);
                    contact = texture(_ContactShadowTexture, screenUV).r;
                }
                if (_ShowContact > 0.5) return vec4(vec3(contact), 1);

                float shadow = min(l.shadowAttenuation, contact);
                vec3 c = albedo * (l.color * saturate(dot(n, l.direction)) * shadow + SampleSH(n));
                return vec4(c, 1);
            }
            void main() { fragColor = frag(); }
            #endif
            ENDGLSL
        }
        Pass
        {
            Name "ShadowCaster"
            Tags { "LightMode"="ShadowCaster" }
            ZWrite On ZTest LEqual ColorMask 0
            GLSLPROGRAM
            #define CH23_SHADOW_PASS
            #include "Ch23/Ch23Common.glsl"
            ENDGLSL
        }
        Pass
        {
            Name "DepthOnly"
            Tags { "LightMode"="DepthOnly" }
            ZWrite On ColorMask R
            GLSLPROGRAM
            #define CH23_DEPTH_PASS
            #include "Ch23/Ch23Common.glsl"
            ENDGLSL
        }
    }
}