Unity URP14.0自定义后处理教程

前言

在 Unity URP 14.0 中实现自定义后处理效果,需要通过 Renderer Features 和 Scriptable Render Passes 实现。以下是详细步骤:

对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一起交流一下开发经验呀!

1. 创建后处理着色器

创建一个全屏后处理 Shader(如 Shaders/PostProcessing/InvertColors.shader):

Shader "Custom/InvertColors"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" }

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            struct Attributes
            {
                float4 positionOS : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct Varyings
            {
                float2 uv : TEXCOORD0;
                float4 positionHCS : SV_POSITION;
            };

            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);

            Varyings vert(Attributes IN)
            {
                Varyings OUT;
                OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
                OUT.uv = IN.uv;
                return OUT;
            }

            half4 frag(Varyings IN) : SV_Target
            {
                half4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uv);
                // 反色效果
                return 1 - color;
            }
            ENDHLSL
        }
    }
}

2. 创建 Render Pass

创建 C# 脚本 InvertColorsPass.cs

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class InvertColorsPass : ScriptableRenderPass
{
    private Material _material;
    private RTHandle _cameraColorTarget;

    public InvertColorsPass(Material material)
    {
        _material = material;
        renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing; // 在后期处理后执行
    }

    public void SetTarget(RTHandle colorHandle)
    {
        _cameraColorTarget = colorHandle;
    }

    public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
    {
        ConfigureTarget(_cameraColorTarget);
    }

    public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    {
        if (_material == null) return;
        
        CommandBuffer cmd = CommandBufferPool.Get("Invert Colors Pass");
        using (new ProfilingScope(cmd, new ProfilingSampler("InvertColors")))
        {
            // 全屏绘制
            Blitter.BlitCameraTexture(cmd, _cameraColorTarget, _cameraColorTarget, _material, 0);
        }
        context.ExecuteCommandBuffer(cmd);
        CommandBufferPool.Release(cmd);
    }
}

3. 创建 Renderer Feature

创建 InvertColorsFeature.cs

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class InvertColorsFeature : ScriptableRendererFeature
{
    [System.Serializable]
    public class Settings
    {
        public Material material;
        public bool isEnabled = true;
    }

    public Settings settings = new Settings();
    private InvertColorsPass _pass;

    public override void Create()
    {
        if (settings.material == null) 
        {
            Debug.LogError("Material not assigned in InvertColorsFeature");
            return;
        }
        _pass = new InvertColorsPass(settings.material);
        _pass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        if (!settings.isEnabled) return;
        
        // 获取相机颜色目标
        var cameraColorTarget = renderer.cameraColorTargetHandle;
        _pass.SetTarget(cameraColorTarget);
        renderer.EnqueuePass(_pass);
    }

    public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
    {
        if (renderingData.cameraData.cameraType == CameraType.Game)
        {
            _pass.ConfigureInput(ScriptableRenderPassInput.Color);
        }
    }
}

4. 配置 URP Renderer

  1. 创建材质
  • 将步骤 1 的 Shader 拖到材质球上,创建 Materials/InvertColorsMat.mat
  • 添加 Renderer Feature
  • 打开 URP 配置文件(如 UniversalRP-HighQuality
  • 选择使用的 Renderer(如 Forward Renderer
  • 点击 Add Renderer Feature → Custom → InvertColorsFeature
  • 将材质 InvertColorsMat 拖入 Feature 的 Material 槽

5. 测试效果

  • 运行场景,屏幕颜色将被反色(白变黑、红变青等)

关键点说明

  1. 执行时机
    RenderPassEvent.AfterRenderingPostProcessing 确保在 URP 内置后处理之后执行。
  2. 纹理处理
    Blitter.BlitCameraTexture 是 URP 14+ 推荐的全屏绘制方法。
  3. 性能优化
  • 使用 CommandBufferPool 减少 GC
  • 通过 ProfilingScope 标记性能区间
  • 扩展性
    可通过修改 Shader 实现更多效果(模糊、边缘检测等):
// 示例:高斯模糊
half4 frag(Varyings IN) : SV_Target
{
    half4 color = 0;
    for (int i = -2; i <= 2; i++) {
        for (int j = -2; j <= 2; j++) {
            float2 offset = float2(i, j) * _BlurSize;
            color += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uv + offset);
        }
    }
    return color / 25;
}

常见问题排查

  1. 效果未生效
  • 检查材质是否赋给 Feature
  • 确认 Renderer Feature 已启用
  • 检查 Shader 编译错误(控制台 > Shader 消息)
  • 性能问题
  • 避免每帧创建临时 RT(使用 RTHandle 复用)
  • 复杂效果使用降采样(如 RenderTextureDescriptor 设置 width/heightScale=0.5
  • 移动端兼容
  • Shader 中添加 #pragma target 3.5
  • 避免分支和循环

提示:URP 14.0+ 移除了 v2f_img 等旧结构,需使用 Core.hlsl 中的标准函数。

更多教学视

Unity3D​www.bycwedu.com/promotion_channels/2146264125

你可能感兴趣的:(unity,游戏引擎,性能优化,Unity3D,spring,java)