我们知道可编程的渲染管线(SRP)是通用渲染管线(URP)和高清渲染管线(HDRP)的基础。而 Unity 可编程的渲染管道(SRP)的核心功能之一就是可以编写自己的 Feature 并将其添加到渲染中,而无需从头开始构建整个渲染系统。
URP 已经为我们提供了很多的后处理效果,但是我们如果想得到更多的效果的话,这里就要去扩展 URP 的 Volume。这就要用到 URP 提供的 RendererFeature 的功能,我们可以通过这个自行添加一个 pass 管理我们的自定义 Volume。
在 Project 窗口点击 Create>Rendering>Universal Render Pipeline>Render Feature,这样我们就可以在 Assets 中找到这个 CustomRenderPassFeature 脚本。
结构解析¶
“CustomRenderPassFeature”负责把这个 Render Pass 加到 Renderer 里面。Render Feature 可以在渲染管线的某个时间点增加一个 Pass 或者多个 Pass。
可以看到我们的 Scriptable Renderer Feature 由两个类 CustomRenderPassFeature 与 CustomRenderPass 组成,CustomRenderPassFeature 类继承自 ScriptableRendererFeature,CustomRenderPass 类继承自 ScriptableRenderPass。
ScriptableRenderPass¶
Create,¶
用来初始化这个Feature的资源,
/// <summary> /// 用来初始化这个资源 /// </summary> public override void Create() { volumeLightingPass = new VolumeLightingPass(settings.Event); }
负责实际的渲染工作,重要的是要有 RenderPassEvent,它里面有 Pass 执行的时间点,用来控制每个 Pass 的执行顺序
public enum RenderPassEvent
{
BeforeRendering = 0,
BeforeRenderingShadows = 50,
AfterRenderingShadows = 100,
BeforeRenderingPrePasses = 150,
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Obsolete, to match the capital from 'Prepass' to 'PrePass' (UnityUpgradable) -> BeforeRenderingPrePasses")]
BeforeRenderingPrepasses = 151,
AfterRenderingPrePasses = 200,
BeforeRenderingGbuffer = 210,
AfterRenderingGbuffer = 220,
BeforeRenderingDeferredLights = 230,
AfterRenderingDeferredLights = 240,
BeforeRenderingOpaques = 250,
AfterRenderingOpaques = 300,
BeforeRenderingSkybox = 350,
AfterRenderingSkybox = 400,
BeforeRenderingTransparents = 450,
AfterRenderingTransparents = 500,
BeforeRenderingPostProcessing = 550,
AfterRenderingPostProcessing = 600,
AfterRendering = 1000,
}
AddRenderPasses¶
AddRenderPasses() 在 Renderer 中插入一个或多个 ScriptableRenderPass,对这个 Renderer 每个摄像机都设置一次。
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
volumeLightingPass.Setup(renderer.cameraColorTarget);
renderer.EnqueuePass(volumeLightingPass);
}
Configure()¶
在执行渲染过程之前,Renderer 将调用此方法。如果需要配置渲染目标及其清除状态,并创建临时渲染目标纹理,那就要重写这个方法。如果渲染过程未重写这个方法,则该渲染过程将渲染到激活状态下 Camera 的渲染目标。
Execute()¶
是这个类的核心方法,定义我们的执行规则;包含渲染逻辑,设置渲染状态,绘制渲染器或绘制程序网格,调度计算等等。
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
if (!renderingData.cameraData.postProcessEnabled) return;
var stac = VolumeManager.instance.stack;
volumeLighting = stac.GetComponent <VolumeLighting> ();
if (volumeLighting == null)
{
Debug.LogError("VolumLighting为空 ");
return;
}
if (!volumeLighting.IsActive())
{
return;
}
var cmd = CommandBufferPool.Get(k_RenderTag);
Render(cmd, ref renderingData);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}