前言
在 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 的 Shader 拖到材质球上,创建
Materials/InvertColorsMat.mat -
添加 Renderer Feature:
-
打开 URP 配置文件(如
UniversalRP-HighQuality) -
选择使用的 Renderer(如
Forward Renderer) -
点击 Add Renderer Feature → Custom →
InvertColorsFeature -
将材质
InvertColorsMat拖入 Feature 的 Material 槽
5. 测试效果
- 运行场景,屏幕颜色将被反色(白变黑、红变青等)
关键点说明
- 执行时机:
RenderPassEvent.AfterRenderingPostProcessing确保在 URP 内置后处理之后执行。 - 纹理处理:
Blitter.BlitCameraTexture是 URP 14+ 推荐的全屏绘制方法。 - 性能优化:
-
使用
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;
}
常见问题排查
- 效果未生效:
-
检查材质是否赋给 Feature
-
确认 Renderer Feature 已启用
-
检查 Shader 编译错误(控制台 > Shader 消息)
-
性能问题:
-
避免每帧创建临时 RT(使用
RTHandle复用) -
复杂效果使用降采样(如
RenderTextureDescriptor设置width/heightScale=0.5) -
移动端兼容:
-
Shader 中添加
#pragma target 3.5 -
避免分支和循环
提示:URP 14.0+ 移除了 v2f_img 等旧结构,需使用 Core.hlsl 中的标准函数。
更多教学视