GameTech/URP 渲染实战
源码 / Ch05/ClassicLab.shader
Ch05/ClassicLab.shader
// 案例 5.9 经典光照实验台:用关键字自由组合漫反射模型与高光模型
Shader "Cookbook/Ch05/ClassicLab"
{
    Properties
    {
        [MainTexture] _BaseMap("Base Map", 2D) = "white" {}
        [MainColor] _BaseColor("Base Color", Color) = (1, 1, 1, 1)
        [KeywordEnum(Lambert, HalfLambert, Wrap, OrenNayar)] _Diffuse("Diffuse Model", Float) = 0
        [KeywordEnum(None, Phong, BlinnPhong)] _Specular("Specular Model", Float) = 2
        _Wrap("Wrap", Range(0, 1)) = 0.5
        _Roughness("Oren-Nayar Sigma", Range(0, 1.5)) = 0.5
        _SpecColor("Specular Color", Color) = (0.2, 0.2, 0.2, 1)
        _Smoothness("Smoothness", Range(0, 1)) = 0.6
        _AmbientStrength("Ambient Strength", Range(0, 1)) = 1
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" "Queue"="Geometry" }

        HLSLINCLUDE
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

        CBUFFER_START(UnityPerMaterial)
            float4 _BaseMap_ST;
            half4  _BaseColor;
            half   _Wrap;
            half   _Roughness;
            half4  _SpecColor;
            half   _Smoothness;
            half   _AmbientStrength;
        CBUFFER_END
        ENDHLSL

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

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma shader_feature_local_fragment _DIFFUSE_LAMBERT _DIFFUSE_HALFLAMBERT _DIFFUSE_WRAP _DIFFUSE_ORENNAYAR
            #pragma shader_feature_local_fragment _SPECULAR_NONE _SPECULAR_PHONG _SPECULAR_BLINNPHONG
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            #include "Assets/Cookbook/Ch05/ClassicLighting.hlsl"

            TEXTURE2D(_BaseMap);
            SAMPLER(sampler_BaseMap);

            struct Attributes
            {
                float4 positionOS : POSITION;
                float3 normalOS   : NORMAL;
                float2 uv         : TEXCOORD0;
            };

            struct Varyings
            {
                float4 positionCS : SV_POSITION;
                float2 uv         : TEXCOORD0;
                float3 positionWS : TEXCOORD1;
                float3 normalWS   : TEXCOORD2;
            };

            Varyings vert(Attributes input)
            {
                Varyings output;
                VertexPositionInputs pos = GetVertexPositionInputs(input.positionOS.xyz);
                output.positionCS = pos.positionCS;
                output.positionWS = pos.positionWS;
                output.normalWS = TransformObjectToWorldNormal(input.normalOS);
                output.uv = TRANSFORM_TEX(input.uv, _BaseMap);
                return output;
            }

            half4 frag(Varyings input) : SV_Target
            {
                half3 albedo = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv).rgb * _BaseColor.rgb;
                float3 N = normalize(input.normalWS);
                float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);
                Light mainLight = GetMainLight();
                float3 L = mainLight.direction;
                half3 radiance = mainLight.color * mainLight.distanceAttenuation;

            #if defined(_DIFFUSE_HALFLAMBERT)
                float d = DiffuseHalfLambert(N, L, 2.0);
            #elif defined(_DIFFUSE_WRAP)
                float d = DiffuseWrap(N, L, _Wrap);
            #elif defined(_DIFFUSE_ORENNAYAR)
                float d = DiffuseOrenNayar(N, L, V, _Roughness);
            #else
                float d = DiffuseLambert(N, L);
            #endif

                float n = ShininessFromSmoothness(_Smoothness);
            #if defined(_SPECULAR_PHONG)
                float s = SpecularPhong(N, L, V, n);
            #elif defined(_SPECULAR_BLINNPHONG)
                float s = SpecularBlinnPhong(N, L, V, n);
            #else
                float s = 0.0;
            #endif

                half3 color = (albedo * d + _SpecColor.rgb * s) * radiance;
                color += albedo * SampleSH(N) * _AmbientStrength;
                return half4(color, 1);
            }
            ENDHLSL
        }

        // ---- 投影与深度:本章先照抄,原理见第 6 章 ----
        Pass
        {
            Name "ShadowCaster"
            Tags { "LightMode"="ShadowCaster" }
            ZWrite On
            ZTest LEqual
            ColorMask 0

            HLSLPROGRAM
            #pragma vertex ShadowDepthVert
            #pragma fragment ShadowDepthFrag
            #pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW
            #include "Assets/Cookbook/Ch05/Ch05ShadowDepth.hlsl"
            ENDHLSL
        }

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

            HLSLPROGRAM
            #pragma vertex DepthOnlyVert
            #pragma fragment DepthOnlyFrag
            #include "Assets/Cookbook/Ch05/Ch05ShadowDepth.hlsl"
            ENDHLSL
        }
    }
}