GameTech/URP 渲染实战
源码 / shaders/Ch17/Inflate.glsl
shaders/Ch17/Inflate.glsl
// 膨胀 / 呼吸:沿某个方向把顶点推出去。(GLSL 版)
//   方向 = 网格法线:最简单,但硬边模型(立方体)的同一位置有多个法线不同的顶点,推开后会裂缝;
//   方向 = 从中心指向顶点:同一位置的顶点方向相同,硬边不会裂开(适合大致凸的形体)。
// 呼吸:振幅随时间做正弦,相位再加上沿 Y 的偏移,就成了一道从下往上走的“脉冲”。
Shader "Cookbook/Ch17/Inflate"
{
    SubShader
    {
        Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" "Queue"="Geometry" }

        GLSLINCLUDE
        #pragma shader_feature_local_vertex _DIR_NORMAL _DIR_RADIAL
        uniform vec4 _BaseColor;
        uniform float _Amount, _PulseFreq, _Speed, _Phase;
        #include "Ch17/VertexAnimCommon.glsl"

        void Deform(inout VAAttributes v)
        {
        #if defined(_DIR_RADIAL)
            vec3 dir = normalize(v.positionOS.xyz);       // 同一位置 → 同一方向,硬边不裂
        #else
            vec3 dir = v.normalOS;
        #endif
            // 呼吸:0..1 之间往复;_PulseFreq > 0 时不同高度相位不同,形成向上传播的脉冲
            float t = _Time.y * _Speed + _Phase;
            float breath = sin(t - v.positionOS.y * _PulseFreq) * 0.5 + 0.5;
            v.positionOS.xyz += dir * _Amount * breath;
            // 均匀膨胀不改变光滑表面的法线方向,这里保持原法线
        }

        #include "Ch17/VertexAnimPasses.glsl"
        ENDGLSL

        Pass
        {
            Name "ForwardLit"
            Tags { "LightMode"="UniversalForwardOnly" }
            GLSLPROGRAM
            #ifdef VERTEX
            void main() { VAForwardVert(); }
            #endif
            #ifdef FRAGMENT
            void main()
            {
                fragColor = vec4(VALighting(_BaseColor.rgb, normalize(normalWS), positionWS, 0.5, 48.0), 1.0);
            }
            #endif
            ENDGLSL
        }

        Pass
        {
            Name "ShadowCaster"
            Tags { "LightMode"="ShadowCaster" }
            ZWrite On ZTest LEqual ColorMask 0
            GLSLPROGRAM
            #ifdef VERTEX
            void main() { VAShadowVert(); }
            #endif
            #ifdef FRAGMENT
            void main() { VANullFrag(); }
            #endif
            ENDGLSL
        }

        Pass
        {
            Name "DepthOnly"
            Tags { "LightMode"="DepthOnly" }
            ZWrite On ColorMask R
            GLSLPROGRAM
            #ifdef VERTEX
            void main() { VADepthVert(); }
            #endif
            #ifdef FRAGMENT
            void main() { VANullFrag(); }
            #endif
            ENDGLSL
        }
    }
}