关于URP中后处理的博客一直没有找到写的比较直白的,现在自己搞清楚了,决定用通俗的语言记录一下,其实流程极其简单
要实现功能,离不开下图这三个文件
Volume文件用于在面板中设置参数
ReaderFeature包含核心渲染逻辑
Shader文件用于具体实现画面效果(自由发挥时刻)
下面是一个实现获取深度纹理的示例,用于理解URP下的后处理流程
1.Volume
此文件主要用于在volume组件中添加对效果的控制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class CustomVolume : VolumeComponent, IPostProcessComponent
{
[Tooltip("颜色")]
public ColorParameter color = new ColorParameter(Color.white);
public bool IsActive()
{
throw new System.NotImplementedException();
}
public bool IsTileCompatible()
{
throw new System.NotImplementedException();
}
}
2.RenderFeature
此文件为后处理渲染配置 ,可以说是核心文件。
首先,需要一个存储渲染配置信息的类,没什么具体的要求,很多博主喜欢放在RenderFeature类内,最好还是单独建一个文件,这样之后做其他效果也可以通用。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.Universal;
/// <summary>
/// 渲染特性配置信息
/// </summary>
[System.Serializable]
public class RenderFeatureSettings
{
//渲染发生的阶段,具体信息可以在枚举类RenderPassEvent中查看
public RenderPassEvent renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing;
//后处理用到的shader
public Shader shader;
public RenderFeatureSettings()
{
}
public RenderFeatureSettings(RenderPassEvent renderPassEvent, string shaderStr)
{
this.renderPassEvent = renderPassEvent;
this.shader = Shader.Find(shaderStr);
}
}
重头戏,RenderFeature类,此类作用是实现渲染的逻辑,需要在管线配置文件中点击Add Renderer Feature添加,如图所示。
类中还包含一个ScriptableRenderPass的子类。
代码里需要解释的地方已经写上注释,重点说几个方法:
1.CustomRenderPassFeature.Create
此方法在点击Add Renaderer Feature后触发
2.CustomRenderPass.Execute
渲染的执行,需要在此方法中写具体的渲染逻辑
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class CustomRenderPassFeature : ScriptableRendererFeature
{
//配置信息
public RenderFeatureSettings settings;
//自定义的渲染pass
CustomRenderPass m_ScriptablePass;
private void OnEnable()
{
//配置信息创建最好放在OnEnable里,因为有调用Shader.Find,此方法不能在ScriptableObject子类的构造函数中调用
settings = new RenderFeatureSettings(RenderPassEvent.BeforeRenderingPostProcessing, "Shader Graphs/Test");
}
public override void Create()
{
//将shader和管线的渲染阶段设置好
m_ScriptablePass = new CustomRenderPass(settings.shader);
m_ScriptablePass.renderPassEvent = settings.renderPassEvent;
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
m_ScriptablePass.Setup(m_ScriptablePass.renderPassEvent, renderer.cameraColorTarget, RenderTargetHandle.CameraTarget);
//添加pass到渲染队列中
renderer.EnqueuePass(m_ScriptablePass);
}
class CustomRenderPass : ScriptableRenderPass
{
CustomVolume customColor;
Material mat;
RenderTargetIdentifier m_Source;
RenderTargetHandle m_Destination;
//用以获取CommandBuffer的字符串,个人理解此字符串用于给获取到的CommandBuffer标记一个名字,方便在FrameDebbuger中查看
const string k_RenderPostProcessingTag = "Render AdditionalPostProcessing Effects";
private Shader shader;
public CustomRenderPass(Shader shader)
{
this.shader = shader;
//创建pass对应的材质,在后续CommandBuffer的渲染中会用到
mat = CoreUtils.CreateEngineMaterial(shader);
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
//获取Volume中的信息
VolumeStack stack = VolumeManager.instance.stack;
customColor = stack.GetComponent<CustomVolume>();
//获取CommandBuffer
var cmd = CommandBufferPool.Get(k_RenderPostProcessingTag);
RenderTargetIdentifier source = renderingData.cameraData.renderer.cameraColorTarget;
RenderTextureDescriptor inRTDesc = renderingData.cameraData.cameraTargetDescriptor;
inRTDesc.depthBufferBits = 0;
int destination = Shader.PropertyToID("T1");
//材质上设置深度图的颜色
mat.SetColor("_Color",bloomColor.color.value);
cmd.BeginSample("MyPostProccess");
// 获取一张临时RT
cmd.GetTemporaryRT(destination, inRTDesc.width, inRTDesc.height, 0, FilterMode.Bilinear, RenderTextureFormat.DefaultHDR); //申请一个临时图像,并设置相机rt的参数进去
cmd.Blit(source, destination);
cmd.Blit(destination, source, mat, 0);
cmd.EndSample("MyPostProccess!");
cmd.ReleaseTemporaryRT(destination);
//执行CommandBuffer
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
public void Setup(RenderPassEvent @event, RenderTargetIdentifier source, RenderTargetHandle destination)
{
renderPassEvent = @event;
m_Source = source;
m_Destination = destination;
}
}
}
3.Shader
可以使用ShaderGraph写,也可以不用,本文将使用ShaderGraph。
就是简单的获取深度图进行颜色的混合,效果如下。