URP源码笔记-渲染器(Renderer)
Renderer的创建依稀还记得上个文章的一个方法叫:RenderSingleCamera
RenderSingleCamera(ScriptableRenderContext context, CameraData cameraData, bool anyPostProcessingEnabled)Unity里面的渲染,是以相机为单位的。而各个相机会在不同的情景有不一样的表现,这时候就需要单独设置相机的参数。 在RenderSingleCamera方法中,调用了InitializeCameraData方法初始化了这些参数。 在UniversalRenderPipelineCore.cs中定义了CameraData,里面包含一个ScriptableRenderer
//UniversalRenderPipelineCore.cs
public struct CameraData
{
Matrix4x4 m_ViewMatrix;
Matrix4x4 m_ProjectionMatrix;
//Camera实例
public Camera camera;
//各种相机参数
public CameraRenderType renderType;
public RenderTexture targetTexture;
public RenderTextureDescriptor cameraTargetDescriptor;
internal Rect pixelRect;
...略
//!!!这里定义了ScriptableRenderer
public ScriptableRenderer renderer;
}在InitializeAdditionalCameraData中,为CameraData的renderer赋值
static void InitializeAdditionalCameraData(Camera camera, UniversalAdditionalCameraData additionalCameraData, bool resolveFinalTarget, ref CameraData cameraData)
{
bool isSceneViewCamera = cameraData.isSceneViewCamera;
if (isSceneViewCamera)
{
cameraData.renderer = asset.scriptableRenderer;
}
else if (additionalCameraData != null)
{
cameraData.renderer = additionalCameraData.scriptableRenderer;
}
else
{
cameraData.renderer = asset.scriptableRenderer;
}
}pipeline asset中获取scriptableRenderer
public ScriptableRenderer scriptableRenderer
{
get
{
if (scriptableRendererData.isInvalidated || m_Renderers == null)
{
DestroyRenderer(ref m_Renderers);
m_Renderers = scriptableRendererData.InternalCreateRenderer();
}
return m_Renderers;
}
}在UniversalRenderPipeline的代码中是这么获取Renderer的,实际上ScriptableRenderer是个抽象类,URP只是其中的一种实现。然后自定义管线也是同样的方式去处理。
SRP的几个重要class
URP类中的render调用流程
Setup,SetupLights,SetupCullingParameters,FinishRendering这几个是虚函数,定制管线的时候需要自定义,例如:URP就有自己的实现。
ScriptableRenderer里面的Execute方法
先说说ScriptableRenderer中我认为比较重要的变量个方法吧:
[*]m_ActiveRenderPassQueue
[*]保存着当前的所有ScriptableRenderPass
[*]EnqueuePass方法:添加pass
[*]ExecuteBlock方法:一个block是有范围的,根据blockRanges里面的下标范围,从m_ActiveRenderPassQueue中取出pass,并执行
[*]BlockIndex
[*]有四种,BeforeRendering, MainRenderingOpaque, MainRenderingTransparent, AfterRendering
[*]根据
[*]执行RenderPassBlock的顺序,如果有在framedebug中查看,可以对比下看看
[*]ExecuteBlock(RenderPassBlock.BeforeRendering
[*]ExecuteBlock(RenderPassBlock.MainRenderingOpaque
[*]ExecuteBlock(RenderPassBlock.MainRenderingTransparent
[*]ExecuteBlock(RenderPassBlock.AfterRendering
[*]m_RendererFeatures
[*]RenderData中的Feature填入到m_RendererFeatures
public void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get();
// 开始渲染,调用pass的OnCameraSetup,收集指令然后发送。
InternalStartRendering(context, ref renderingData);
// 清理渲染状态,如禁用一些关键字,后续根据pass需要开启
ClearRenderingState(cmd);
// 设置_Time,_SinTime,_CosTime,unity_DeltaTime,_TimeParameters的值
SetShaderTimeValues(cmd, time, deltaTime, smoothDeltaTime);
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
// 对render pass做排序
SortStable(m_ActiveRenderPassQueue);
//根据hash值把合并pass
SetupNativeRenderPassFrameData(cameraData, useRenderPassEnabled);
//填充rendersBlocks
using var renderBlocks = new RenderBlocks(m_ActiveRenderPassQueue);
//初始化光照
SetupLights(context, ref renderingData);
ExecuteBlock(RenderPassBlock.BeforeRendering, in renderBlocks, context, ref renderingData);
//设置摄像机的shader变量
SetPerCameraShaderVariables(cmd, ref cameraData);
SetShaderTimeValues(cmd, time, deltaTime, smoothDeltaTime);
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
// 渲染不透明物体
ExecuteBlock(RenderPassBlock.MainRenderingOpaque, in renderBlocks, context, ref renderingData);
// 渲染透明物体
ExecuteBlock(RenderPassBlock.MainRenderingTransparent, in renderBlocks, context, ref renderingData);
// 绘制Gizmos
DrawGizmos(context, camera, GizmoSubset.PreImageEffects);
// 渲染之后,后处理or播视频
ExecuteBlock(RenderPassBlock.AfterRendering, in renderBlocks, context, ref renderingData);
DrawWireOverlay(context, camera);
DrawGizmos(context, camera, GizmoSubset.PostImageEffects);
//finishRendering事件
InternalFinishRendering(context, cameraData.resolveFinalTarget);
//清理,下次render再次setup
for (int i = 0; i < m_ActiveRenderPassQueue.Count; ++i)
{
m_ActiveRenderPassQueue.m_ColorAttachmentIndices.Dispose();
m_ActiveRenderPassQueue.m_InputAttachmentIndices.Dispose();
}
//发送指令到context
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}添加和执行pass
添加pass:EnqueuePass方法。在URP中,setup的添加URP实现的pass。renderfeature里面也会加入相应的pass
public void EnqueuePass(ScriptableRenderPass pass)
{
m_ActiveRenderPassQueue.Add(pass);
if (disableNativeRenderPassInFeatures) pass.useNativeRenderPass = false;
}用到的pass会存储m_ActiveRenderPassQueue,然后Execute方法中会new一个RenderBlocks,来组织pass。
执行pass:ExecuteBlock->ExecuteRenderPass
void ExecuteRenderPass(ScriptableRenderContext context, ScriptableRenderPass renderPass,
ref RenderingData renderingData)
{
ref CameraData cameraData = ref renderingData.cameraData;
CommandBuffer cmd = CommandBufferPool.Get();
//调用pass的Configure,进行一些配置,如attachment
renderPass.Configure(cmd, cameraData.cameraTargetDescriptor);
//配置color,depth RT,里面调用的是SetRenderTarget->CoreUtils.SetRenderTarget
SetRenderPassAttachments(cmd, renderPass, ref cameraData);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
//执行pass
renderPass.Execute(context, ref renderingData);
}pass相关
ScriptableRenderPass是一个abstract class,一个pass实现需要继承它并且实现具体逻辑。 从构造函数,可以知道相关渲染数据:
public ScriptableRenderPass()
{
renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
//颜色缓冲
m_ColorAttachments = new RenderTargetIdentifier[] { BuiltinRenderTextureType.CameraTarget, 0, 0, 0, 0, 0, 0, 0 };
m_InputAttachments = new RenderTargetIdentifier[] { -1, -1, -1, -1, -1, -1, -1, -1 };
m_InputAttachmentIsTransient = new bool[] { false, false, false, false, false, false, false, false };
//深度缓冲
m_DepthAttachment = BuiltinRenderTextureType.CameraTarget;
m_ColorStoreActions = new RenderBufferStoreAction[] { RenderBufferStoreAction.Store, 0, 0, 0, 0, 0, 0, 0 };
m_DepthStoreAction = RenderBufferStoreAction.Store;
m_OverriddenColorStoreActions = new bool[] { false, false, false, false, false, false, false, false };
m_OverriddenDepthStoreAction = false;
//缓冲清理标记,Color, Depth,Stencil
m_ClearFlag = ClearFlag.None;
m_ClearColor = Color.black;
overrideCameraTarget = false;
isBlitRenderPass = false;
profilingSampler = new ProfilingSampler($&#34;Unnamed_{nameof(ScriptableRenderPass)}&#34;);
useNativeRenderPass = true;
renderTargetWidth = -1;
renderTargetHeight = -1;
renderTargetSampleCount = -1;
renderPassQueueIndex = -1;
renderTargetFormat = new GraphicsFormat[]
{
GraphicsFormat.None, GraphicsFormat.None, GraphicsFormat.None,
GraphicsFormat.None, GraphicsFormat.None, GraphicsFormat.None, GraphicsFormat.None, GraphicsFormat.None
};
depthOnly = false;
}方法:
[*]ConfigureInput
[*]配置input(None,Depth,Normal,Color,Motion)
[*]ConfigureTarget
[*]配置当前pass的render targets,如ColorAttachment、DepthAttachment
[*]ConfigureClear
[*]配置clearFlag和clearColor
[*]OnCameraSetup (虚函数)
[*]渲染一个camera之前的回调
[*]Configure (虚函数)
[*]定制pass可以自定义里面的configure逻辑
[*]OnCameraCleanup (虚函数)
[*]事件回调
[*]OnFinishCameraStackRendering (虚函数)
[*]事件回调
[*]Execute (抽象函数)
[*]pass的execute逻辑
[*]CreateDrawingSettings
[*]根据当前渲染状态创建绘制设置
页:
[1]