GameTech/URP 渲染实战
源码 / shaders/Ch26/RadialBlur.glsl
shaders/Ch26/RadialBlur.glsl
// 案例 26.5:径向模糊——沿“像素 → 中心”的方向多次采样求平均。
Shader "Cookbook/Ch26/RadialBlur"
{
    SubShader
    {
        Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" }
        ZTest Always ZWrite Off Cull Off
        Pass
        {
            Name "RadialBlur"
            GLSLPROGRAM
            uniform vec4  _RadialParams;   // xy 中心, z 强度, w 采样数
            uniform float _ClearRadius;

            VARYING vec2 texcoord;
            #ifdef VERTEX
            // Blit.hlsl 的 Vert:用 gl_VertexID 生成盖住全屏的大三角形(_BlitTexture、_BlitTexture_TexelSize 等在 Core.glsl 里声明)
            void main()
            {
                vec2 p = vec2((gl_VertexID << 1) & 2, gl_VertexID & 2);
                texcoord = p * _BlitScaleBias.xy + _BlitScaleBias.zw;
                gl_Position = vec4(p * 2.0 - 1.0, 0.0, 1.0);
            }
            #endif

            #ifdef FRAGMENT
            float InterleavedGradientNoise(vec2 pixel)
            {
                return fract(52.9829189 * fract(dot(pixel, vec2(0.06711056, 0.00583715))));
            }

            vec4 Frag()
            {
                vec2 uv = texcoord;
                vec2 center = _RadialParams.xy;
                vec2 dir = uv - center;                         // 指向外侧,长度 = 到中心的距离

                // 中心一圈保持清晰:按宽高比修正成正圆后再算距离
                float aspect = _ScreenParams.x / _ScreenParams.y;
                float dist = length(dir * vec2(aspect, 1.0));
                float amount = _RadialParams.z * smoothstep(_ClearRadius, _ClearRadius + 0.25, dist);

                int count = int(_RadialParams.w);
                // 每个像素的起点加一点抖动,把“分层的重影”变成细噪点
                float jitter = InterleavedGradientNoise(uv * _ScreenParams.xy);
                vec3 sum = vec3(0.0);
                for (int i = 0; i < count; i++)
                {
                    float t = (float(i) + jitter) / float(count);   // 0..1
                    vec2 s = uv - dir * amount * 0.3 * t;           // 向中心方向收缩
                    sum += texture(_BlitTexture, s).rgb;
                }
                return vec4(sum / float(count), 1.0);
            }
            void main() { fragColor = Frag(); }
            #endif
            ENDGLSL
        }
    }
}