Unity Shader 实战屏幕颜色抓取实现径向模糊 (URP)

发布时间:2026/7/10 6:49:10

Unity Shader 实战屏幕颜色抓取实现径向模糊 (URP) 径向模糊(Radial Blur)是一种经典的后处理效果,它能够创建出动态的速度感或聚焦效果。在游戏开发中,径向模糊常用于:高速运动的速度线效果聚焦中心的视觉引导爆炸或冲击波的视觉表现特殊技能释放的炫酷效果本教程将带你一步步在Unity URP(Universal Render Pipeline)环境下,通过屏幕颜色抓取技术实现径向模糊效果。 核心概念什么是屏幕颜色抓取?屏幕颜色抓取(Screen Color Grab)是一种后处理技术,它允许Shader访问当前渲染的屏幕内容,并将其作为纹理进行处理。在Unity中,这通过_CameraColorTexture或自定义的Render Texture来实现。什么是径向模糊?径向模糊是一种从中心点向外辐射的模糊效果。不同于高斯模糊的全方向模糊,径向模糊只沿着从中心到边缘的径向方向进行采样和混合,创造出动态的视觉冲击。完整的径向模糊Shader以下是一个完整的URP径向模糊Shader实现,包含详细的注释:Shader Hidden/RadialBlur { Properties { _MainTex (Texture, 2D) white {} } HLSLINCLUDE #include Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl #include Packages/com.unity.render-pipelines.universal/ShaderLibrary/PostProcessing.hlsl struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; }; struct Varyings { float4 positionCS : SV_POSITION; float2 uv : TEXCOORD0; }; TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); // 模糊参数 float _BlurStrength; // 模糊强度 0.0-1.0 float _BlurRadius; // 模糊半径 0.0-0.5 float2 _Center; // 模糊中心 (屏幕UV坐标) float _SampleCount; // 采样次数 1-32 // 顶点着色器 Varyings Vert(Attributes input) { Varyings output; output.positionCS TransformObjectToHClip(input.positionOS.xyz); output.uv input.uv; return output; } // 片段着色器 - 径向模糊核心算法 half4 Frag(Varyings input) : SV_Target { float2 uv input.uv; float2 center _Center; float2 dir uv - center; // 计算从中心到当前像素的方向 float dist length(dir); // 计算距离中心的距离 // 如果在中心点附近,直接返回原样,避免不必要的计算 if (dist 0.001) { return SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv); } dir normalize(dir); // 归一化方向向量 half4 finalColor half4(0, 0, 0, 0); float totalWeight 0; // 沿径向方向多次采样 for (int i 0; i (int)_SampleCount; i) { // 计算采样偏移量 (0到1之间均匀分布) float t (float)i / (_SampleCount - 1); // 沿径向方向的偏移 float2 offset dir * t * _BlurRadius * _BlurStrength; // 从中心向外采样 half4 sampleColor SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv - offset); // 距离越远,权重越小 (可选的加权策略) float weight 1.0 - t * 0.5; finalColor sampleColor * weight; totalWeight weight; } // 归一化颜色 finalColor / totalWeight; return finalColor; } ENDHLSL SubShader { Tags { RenderType Opaque RenderPipeline UniversalPipeline } Cull Off ZWrite Off ZTest Always Pass { HLSLPROGRAM #pragma vertex Vert #pragma fragment Frag ENDHLSL } } } Shader代码要点解析方向计算: 使用 normalize(uv - center) 计算径向方向多次采样: 通过循环沿径向方向采样不同位置的颜色权重混合: 使用权重因子 1.0 - t * 0.5 让靠近中心的采样点权重更高性能优化: 在中心点附近直接返回,避免不必要的计算创建渲染特效脚本创建RadialBlurEffect.cs文件,用于控制Shader的参数和渲染流程:using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; namespace RenderPipelineEffects { /// /// URP径向模糊效果 - Renderer Feature /// 通过屏幕颜色抓取实现径向模糊效果 /// public class RadialBlurEffect : ScriptableRendererFeature { [System.Serializable] public class Settings { [Header(基础设置)] public Shader shader; public RenderPassEvent renderPassEvent RenderPassEvent.BeforeRenderingPostProcessing; [Header(模糊参数)] [Tooltip(模糊强度 (0.0 - 1.0))] [Range(0f, 1f)] public float blurStrength 0.5f; [Tooltip(模糊半径 (0.0 - 0.5))] [Range(0f, 0.5f)] public float blurRadius 0.2f; [Header(质量设置)] [Tooltip(采样次数 (1 - 32))] [Range(1f, 32f)] public float sampleCount 16f; [Header(中心点设置)] [Tooltip(模糊中心X坐标 (屏幕UV空间 0.0 - 1.0))] [Range(0f, 1f)] public float centerX 0.5f; [Tooltip(模糊中心Y坐标 (屏幕UV空间 0.0 - 1.0))] [Range(0f, 1f)] public float centerY 0.5f; [Header(控制)] [Tooltip(启用/禁用效果)] public bool enableEffect true; } public Settings settings new Settings(); private RadialBlurPass m_ScriptablePass; /// /// 创建渲染通道 /// public override void Create() { m_ScriptablePass new RadialBlurPass(settings); m_ScriptablePass.renderPassEvent settings.renderPassEvent; } /// /// 将渲染通道添加到渲染器 /// public override void AddRenderPasses( ScriptableRenderer renderer, ref RenderingData renderingData) { if (settings.shader null || !settings.enableEffect) return; renderer.EnqueuePass(m_ScriptablePass); } /// /// 径向模糊渲染通道 /// class RadialBlurPass : ScriptableRenderPass { private Settings settings; private Material m_Material; private RTHandle m_TemporaryColorTexture; public RadialBlurPass(Settings settings) { this.settings settings; if (settings.shader ! null) { m_Material new Material(settings.shader); m_Material.hideFlags HideFlags.HideAndDontSave; } } /// /// 摄像机设置 - 分配临时渲染纹理 /// public override void OnCameraSetup( CommandBuffer cmd, ref RenderingData renderingData) { var desc renderingData.cameraData.cameraTargetDescriptor; desc.depthBufferBits 0; // 不需要深度缓冲 RenderingUtils.ReAllocateIfNeeded( ref m_TemporaryColorTexture, desc, FilterMode.Bilinear, TextureWrapMode.Clamp, name: _RadialBlurTemp ); } /// /// 执行渲染通道 - 应用径向模糊效果 /// public override void Execute( CommandBuffer cmd, ref RenderingData renderingData) { if (m_Material null) return; // 获取摄像机颜色目标 var source renderingData.cameraData.renderer.cameraColorTargetHandle; // 设置Shader参数 m_Material.SetFloat(_BlurStrength, settings.blurStrength); m_Material.SetFloat(_BlurRadius, settings.blurRadius); m_Material.SetFloat(_SampleCount, settings.sampleCount); m_Material.SetVector( _Center, new Vector2(settings.centerX, settings.centerY)); // 第一次Blit: 应用模糊效果到临时纹理 Blitter.BlitCameraTexture( cmd, source, m_TemporaryColorTexture, m_Material, 0 ); // 第二次Blit: 将结果拷贝回源纹理 Blitter.BlitCameraTexture( cmd, m_TemporaryColorTexture, source ); } } } }参数详解参数类型范围作用默认值blurStrengthfloat0.0 ~ 1.0控制模糊的整体强度0.5blurRadiusfloat0.0 ~ 0.5控制采样的最大半径0.2sampleCountfloat1 ~ 32采样次数,影响质量与性能16centerXfloat0.0 ~ 1.0模糊中心的X坐标(屏幕空间)0.5centerYfloat0.0 ~ 1.0模糊中心的Y坐标(屏幕空间)0.5使用步骤步骤1: 导入Shader将RadialBlurShader.shader文件拖入Unity项目,Unity会自动编译并生成Shader资源步骤2: 添加Renderer Feature在Project窗口找到URP Renderer Data资源,点击Add Renderer Feature,选择RadialBlurEffect步骤3: 配置参数在Inspector面板中设置Shader引用,调整模糊强度、半径和中心点位置步骤4: 测试效果运行场景,观察径向模糊效果。如果需要动态调整,可以编写C#脚本来控制参数 性能优化建议在移动平台上,建议将sampleCount控制在8-12之间可以使用mipmap降低采样成本考虑使用half精度而非full精度在不显示效果时设置enableEffect为false⚠️ 常见问题效果不显示:检查URP Renderer Data是否正确添加了Renderer Feature性能下降明显:降低sampleCount或blurRadius中心点不对:确保centerX和centerY在0-1范围内Shader编译错误:确认URP版本兼容性,使用正确的include路径 总结本教程详细介绍了在Unity URP环境下实现径向模糊效果的完整流程,包括:✅ 屏幕颜色抓取的基本原理✅ 径向模糊的算法实现✅ URP Renderer Feature的使用✅ 性能优化技巧✅ 动态效果实现方法

相关新闻