Unity RenderFeature Configure和OnCameraSetup之区别
调用顺序
首先,源码描述为:
/// <summary>
/// This method is called by the renderer before rendering a camera
/// Override this method if you need to to configure render targets and their clear state, and to create temporary render target textures.
/// If a render pass doesn't override this method, this render pass renders to the active Camera's render target.
/// You should never call CommandBuffer.SetRenderTarget. Instead call <c>ConfigureTarget</c> and <c>ConfigureClear</c>.
/// </summary>
/// <param name="cmd">CommandBuffer to enqueue rendering commands. This will be executed by the pipeline.</param>
/// <param name="renderingData">Current rendering state information</param>
/// <seealso cref="ConfigureTarget"/>
/// <seealso cref="ConfigureClear"/>
public virtual void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{ }
/// <summary>
/// This method is called by the renderer before executing the render pass.
/// Override this method if you need to to configure render targets and their clear state, and to create temporary render target textures.
/// If a render pass doesn't override this method, this render pass renders to the active Camera's render target.
/// You should never call CommandBuffer.SetRenderTarget. Instead call <c>ConfigureTarget</c> and <c>ConfigureClear</c>.
/// </summary>
/// <param name="cmd">CommandBuffer to enqueue rendering commands. This will be executed by the pipeline.</param>
/// <param name="cameraTextureDescriptor">Render texture descriptor of the camera render target.</param>
/// <seealso cref="ConfigureTarget"/>
/// <seealso cref="ConfigureClear"/>
public virtual void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
{ }
实际上已经表明了其执行顺序:
OnCameraSetup(): before rendering a camera
Configure(): before executing the render pass
即Configure发生在OnCameraSetup之后。
其余注释完全相同,都建议了在其内部使用ConfigureTarget、ConfigureClear。
参数区别
进一步的,进入UnityEngine.Rendering.Universal.ScriptableRenderer可以看到执行逻辑:
public void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
...
ref CameraData cameraData = ref renderingData.cameraData;
...
if (rendererFeatures.Count != 0 && !renderingData.cameraData.isPreviewCamera)
SetupRenderPasses(in renderingData); ⚠️调用了SetupRenderPasses
...
InternalStartRendering(context, ref renderingData);ℹ️ℹ️ℹ️在此处调用了OnCameraSetup
...
{
...ClearRenderingState(cmd);清理相机环境
...更新Shader Time全局变量
}
...
对RenderPass进行排序
SortStable(m_ActiveRenderPassQueue);
...
foreach (var pass in activeRenderPassQueue)
pass.Configure(cmd, cameraData.cameraTargetDescriptor);ℹ️ℹ️ℹ️此处为Configure
...
SetupLights(context, ref renderingData);
...VFX.VFXManager...
...根据Pass的Inject时机,分阶段执行相应Pass的Execute
(执行相应Pass的Execute中安插了一次对SetPerCameraProperties的调用,用于设置相机属性,具体来说是billboard、unity_CameraWorldClipPlanes、_ProjectionParams。
之所以安插在此处执行而不是在初始化阶段执行,解释是用于VR多目适配:每个眼睛都要执行一次此设置)
}
其中InternalStartRendering的核心逻辑为:
for (int i = 0; i < m_ActiveRenderPassQueue.Count; ++i) m_ActiveRenderPassQueue[i].OnCameraSetup(renderingData.commandBuffer, ref renderingData);
可以得出结论:
两者参数没有本质区别,Configure的参数是OnCameraSetup的子集。
但可以看出一点的是,不同Pass间Configure的调用时刻是有序的,SortStable将Pass按照renderPassEvent的注入顺序排序。
除此之外,两者参数中的cmd也相同,都已经过Clear,同时当退出函数后,也会对其进行再一次的Clear。
如果非要说出不同的话,那就是Configure之前OnCameraSetup之后确实发生了CameraSetup:
ClearRenderingState(cmd);
在其中使用了cmd.DisableShaderKeyword设置Keyword,但这通常不会对函数体内产生什么影响:没人会在Configure、OnCameraSetup中处理这些数据。
总结
如果不关心不同Pass间的执行顺序,则Configure中的操作,完全可以在OnCameraSetup中完成。