GameTech/URP 渲染实战
源码 / shaders/Ch05/Phong.glsl
shaders/Ch05/Phong.glsl
// 案例 5.4 Phong 高光:反射向量 R 与视线 V 的夹角决定高光(GLSL 版)
Shader "Cookbook/Ch05/Phong"
{
    SubShader
    {
        Tags { "RenderType"="Opaque" "Queue"="Geometry" }

        GLSLINCLUDE
        uniform vec4  _BaseColor;
        uniform vec4  _SpecColor;
        uniform float _Shininess;
        uniform float _AmbientStrength;
        ENDGLSL

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

            GLSLPROGRAM
            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);
            }
            #endif

            #ifdef FRAGMENT
            void main()
            {
                vec3 N = normalize(normalWS);
                vec3 V = GetWorldSpaceNormalizeViewDir(positionWS);   // 指向相机
                Light mainLight = GetMainLight();
                vec3 L = mainLight.direction;                         // 指向光源
                vec3 radiance = mainLight.color * mainLight.distanceAttenuation;

                float NdotL = dot(N, L);
                vec3 diffuse = _BaseColor.rgb * saturate(NdotL);

                // reflect(i, n) 要求 i 是“射入”方向,所以传 -L
                vec3 R = reflect(-L, N);
                float RdotV = saturate(dot(R, V));
                // 高光指数常常上百,用 float 计算,避免 half 精度下出现色带
                float spec = pow(RdotV, _Shininess);
                // 背光面不应该出现高光(R 可能恰好朝向相机)
                spec *= step(0.0, NdotL);

                vec3 color = (diffuse + _SpecColor.rgb * spec) * radiance;
                color += _BaseColor.rgb * SampleSH(N) * _AmbientStrength;
                fragColor = vec4(color, 1.0);
            }
            #endif
            ENDGLSL
        }

        // ---- 投影与深度:本章先照抄,原理见第 6 章 ----
        Pass
        {
            Name "ShadowCaster"
            Tags { "LightMode"="ShadowCaster" }
            ZWrite On
            ZTest LEqual
            ColorMask 0
            GLSLPROGRAM
            #define SHADOW_PASS
            #include "Ch05/Ch05ShadowDepth.glsl"
            ENDGLSL
        }

        Pass
        {
            Name "DepthOnly"
            Tags { "LightMode"="DepthOnly" }
            ZWrite On
            ColorMask R
            GLSLPROGRAM
            #define DEPTH_PASS
            #include "Ch05/Ch05ShadowDepth.glsl"
            ENDGLSL
        }
    }
}