yukamu 发表于 2023-3-4 13:49

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($"Unnamed_{nameof(ScriptableRenderPass)}");
    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]
查看完整版本: URP源码笔记-渲染器(Renderer)