博客 / 詳情

返回

【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開始探索遊戲渲染】專欄-直達
(歡迎點贊留言探討,更多人加入進來能更加完善這個探索的過程,🙏)
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.