【URP】Unity[RendererFeatures]全屏后处理FullScreenPassRendererFeature

【从UnityURP开始探索游戏渲染】专栏-直达

FullScreenPassRendererFeature是Unity URP渲染管线中用于实现全屏后处理效果的核心组件,它允许开发者在渲染流程的特定阶段插入自定义的全屏着色器效果。

功能与作用

  • 核心功能‌:通过ScriptableRenderPass在URP管线中注入全屏四边形绘制命令,应用自定义Shader实现屏幕空间特效(如模糊、色调调整等)
  • 典型应用场景‌:
    • 屏幕后处理(如Bloom、景深模拟)
    • 全局滤镜效果(黑白化、夜视模式)
    • 特殊视觉特效(扫描线、像素化)

发展历史

  • URP初期‌:需手动编写完整的ScriptableRendererFeature和ScriptableRenderPass类实现全屏效果
  • ‌URP 7.0+ :引入预置的FullScreenPassRendererFeature简化开发流程
  • URP 17.0‌:重构API至RenderGraph系统,优化资源管理机制

原理

FullScreenPassRendererFeature是Unity URP中用于实现全屏后处理效果的核心组件,其底层原理基于URP的可编程渲染管线架构。

核心原理

  • 继承关系‌:继承自ScriptableRendererFeature基类,通过Create()方法初始化自定义的ScriptableRenderPass子类实例
  • 执行流程‌:在URP渲染管线的特定阶段(如不透明物体渲染后)插入全屏绘制命令,通过CommandBuffer调用BlitDrawProcedural实现
  • 资源管理‌:使用RTHandle系统动态管理渲染目标,自动处理不同分辨率下的资源分配与释放

关键代码示例

以下实现一个基础的全屏泛光效果:

  • BloomFeature.cs

    using UnityEngine;
    using UnityEngine.Rendering;
    using UnityEngine.Rendering.Universal;
    
    [System.Serializable]
    public class BloomSettings {
        public float intensity = 1.0f;
        public Color tint = Color.white;
    }
    
    public class BloomFeature : ScriptableRendererFeature {
        public BloomSettings settings = new BloomSettings();
        private BloomPass m_Pass;
    
        public override void Create() {
            m_Pass = new BloomPass(settings);
            m_Pass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
        }
    
        public override void AddRenderPasses(
            ScriptableRenderer renderer, 
            ref RenderingData renderingData) {
            renderer.EnqueuePass(m_Pass);
        }
    }
    
    class BloomPass : ScriptableRenderPass {
        private Material m_Material;
        private BloomSettings m_Settings;
        private RTHandle m_TempTexture;
    
        public BloomPass(BloomSettings settings) {
            m_Settings = settings;
            m_Material = CoreUtils.CreateEngineMaterial("Hidden/Blur");
        }
    
        public override void Configure(CommandBuffer cmd, 
            RenderTextureDescriptor cameraTextureDescriptor) {
            m_TempTexture = RTHandles.Alloc(
                Vector2.one * 0.5f, 
                colorFormat: cameraTextureDescriptor.colorFormat);
        }
    
        public override void Execute(ScriptableRenderContext context, 
            ref RenderingData renderingData) {
            var cmd = CommandBufferPool.Get("BloomPass");
            Blit(cmd, 
                renderingData.cameraData.renderer.cameraColorTargetHandle,
                m_TempTexture, 
                m_Material, 0);
            Blit(cmd, 
                m_TempTexture,
                renderingData.cameraData.renderer.cameraColorTargetHandle);
            context.ExecuteCommandBuffer(cmd);
            CommandBufferPool.Release(cmd);
        }
    
        public override void FrameCleanup(CommandBuffer cmd) {
            m_TempTexture.Release();
        }
    }
    

技术细节

  • 材质控制‌:通过Shader的LightMode标签匹配(如UniversalForward)确定渲染路径
  • 时序控制‌:RenderPassEvent枚举精确控制执行时机(如AfterRenderingOpaques
  • 多Pass协作‌:支持通过多个ScriptableRenderPass实现效果叠加,如先提取亮部再模糊

性能优化

  • 临时纹理复用‌:通过RTHandle的缩放参数实现动态分辨率渲染
  • 命令缓冲池‌:使用CommandBufferPool减少GC开销
  • 材质实例化‌:避免每帧创建新材质

该机制相比传统OnRenderImage方案,在URP中能更好地集成到SRP批处理系统中,且支持XR多通道渲染等高级特性

实现流程示例

以下为完整实现黑白滤镜效果的URP示例:

  • GrayFeature.cs

    using UnityEngine;
    using UnityEngine.Rendering;
    using UnityEngine.Rendering.Universal;
    
    public class GrayRenderFeature : ScriptableRendererFeature {
        public RenderPassEvent renderEvent = RenderPassEvent.AfterRendering;
        public Shader shader;
        private Material grayMaterial;
        private GrayPass grayPass;
    
        public override void Create() {
            grayMaterial = CoreUtils.CreateEngineMaterial(shader);
            grayPass = new GrayPass(grayMaterial, renderEvent);
        }
    
        public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) {
            grayPass.SetTarget(renderer.cameraColorTargetHandle);
            renderer.EnqueuePass(grayPass);
        }
    }
    
    public class GrayPass : ScriptableRenderPass {
        private Material material;
        private RTHandle source;
    
        public GrayPass(Material material, RenderPassEvent passEvent) {
            this.material = material;
            this.renderPassEvent = passEvent;
        }
    
        public void SetTarget(RTHandle colorHandle) {
            source = colorHandle;
        }
    
        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) {
            CommandBuffer cmd = CommandBufferPool.Get("GrayEffect");
            Blitter.BlitCameraTexture(cmd, source, source, material, 0);
            context.ExecuteCommandBuffer(cmd);
            CommandBufferPool.Release(cmd);
        }
    }
    
  • GrayEffect.shader

    Shader "Custom/GrayEffect" {
        Properties {
            _MainTex ("Base (RGB)", 2D) = "white" {}
        }
        SubShader {
            Pass {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
    
                struct appdata {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                struct v2f {
                    float2 uv : TEXCOORD0;
                    float4 vertex : SV_POSITION;
                };
    
                sampler2D _MainTex;
    
                v2f vert (appdata v) {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.uv = v.uv;
                    return o;
                }
    
                fixed4 frag (v2f i) : SV_Target {
                    fixed4 col = tex2D(_MainTex, i.uv);
                    float gray = dot(col.rgb, float3(0.299, 0.587, 0.114));
                    return fixed4(gray, gray, gray, col.a);
                }
                ENDCG
            }
        }
    }
    

参数说明与用例

参数 类型 说明 典型值
renderEvent RenderPassEvent 执行时机 AfterRenderingOpaques
shader Shader 效果着色器 自定义全屏Shader
intensity float 效果强度 0.0-1.0

实际配置步骤‌:

  • 创建URP Renderer Asset(若不存在)
  • 通过Inspector添加FullScreenPassRendererFeature
  • 指定Material并使用ShaderGraph创建效果
  • 调整RenderPassEvent控制执行顺序

性能优化建议

  • 使用RTHandle管理渲染目标避免内存浪费
  • 复杂效果建议结合Volume系统实现参数动态调整
  • 移动端需注意带宽占用,推荐使用Half Resolution处理

【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)

posted @ 2025-11-16 10:13  SmalBox  阅读(8)  评论(0)    收藏  举报