Skip to content

URP Source

zilch edited this page Feb 25, 2021 · 2 revisions

URP源码分析

URP的主入口为UniversalRenderPipeline.Render,源码分析就从这里开始.

Render依次做了如下的事情:

  1. BeginFrameRendering
  2. GraphicsSettings设置
  3. SetupPerFrameShaderConstants
  4. 摄像机排序
  5. 遍历对每个摄像机进行渲染
  6. EndFrameRendering

看Render代码:

protected override void Render(ScriptableRenderContext renderContext, Camera[] cameras)
{
    BeginFrameRendering(renderContext, cameras);

    //颜色空间设置
    GraphicsSettings.lightsUseLinearIntensity = (QualitySettings.activeColorSpace == ColorSpace.Linear);
    //是否开启SRP合批功能
    GraphicsSettings.useScriptableRenderPipelineBatching = asset.useSRPBatcher;
    //相关Shader参数设置
    SetupPerFrameShaderConstants();

#if ENABLE_VR && ENABLE_XR_MODULE
    SetupXRStates();
#endif

    //对摄像机渲染优先级进行排序。这里排序是根据camera的depth进行的
    SortCameras(cameras);

    //针对每个摄像机,进行渲染
    for (int i = 0; i < cameras.Length; ++i)
    {
        var camera = cameras[i];
#if ENABLE_VR && ENABLE_XR_MODULE
        if (IsStereoEnabled(camera) && xrSkipRender)
            continue;
#endif
        //判定是否为GameView的摄像机. 参见CameraType
        //https://docs.unity3d.com/ScriptReference/CameraType.html
        //SceneView和GameView的摄像机,走的渲染流程会有些不一样
        if (IsGameCamera(camera))
        {
            ///关键代码
            RenderCameraStack(renderContext, camera);
        }
        else
        {
            BeginCameraRendering(renderContext, camera);
#if VISUAL_EFFECT_GRAPH_0_0_1_OR_NEWER
            //It should be called before culling to prepare material. When there isn't any VisualEffect component, this method has no effect.
            VFX.VFXManager.PrepareCamera(camera);
#endif
            UpdateVolumeFramework(camera, null);

            RenderSingleCamera(renderContext, camera);
            EndCameraRendering(renderContext, camera);
        }
    }

    EndFrameRendering(renderContext, cameras);
}

可以看出,关键代码在于RenderCameraStack这个函数。 CameraStack是什么?参考官方文档

RenderCameraStack函数实际渲染了一个BaseCamera和归属于它的多个OverlayCamera。内部基本逻辑为:

RenderCamera(baseCamera);

foreach(overlayCamera in baseCamera.stackCameras){
    RenderCamera(overlayCamera);
}

关键代码RenderCamera,内部基本流程为:

  • BeginCameraRendering

    发送RenderPipelineManager.beginCameraRendering事件

  • InitializeCameraData

    初始化CameraData对象

  • RenderSingleCamera

    渲染单个摄像机

  • EndCameraRendering

    发送RenderPipelineManager.endFrameRendering事件

RenderSingleCamera流程

摘取关键代码,并简化后如下:

CommandBuffer cmd = CommandBufferPool.Get(sampler.name);
renderer.Clear(cameraData.renderType);
//裁剪
renderer.SetupCullingParameters(ref cullingParameters, ref cameraData);
var cullResults = context.Cull(ref cullingParameters);
//根据裁剪信息,生成RenderingData
InitializeRenderingData(asset, ref cameraData, ref cullResults, anyPostProcessingEnabled, out var renderingData);

//初始化管线
renderer.Setup(context, ref renderingData);
//渲染
renderer.Execute(context, ref renderingData);

//执行CommandBuffer
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);

//提交
context.Submit();

其中rendererScriptableRenderer对象。这是URP中定义的,URP允许为一个URPAsset配置多个ScriptableRenderer。 ScriptableRenderer负责实现裁剪和光照策略。

Class ScriptableRenderer implements a rendering strategy. It describes how culling and lighting works and the effects supported.

A renderer can be used for all cameras or be overridden on a per-camera basis. It will implement light culling and setup and describe a list of ScriptableRenderPass to execute in a frame. The renderer can be extended to support more effect with additional ScriptableRendererFeature. Resources for the renderer are serialized in ScriptableRendererData.

参考官方文档

ForwardRenderer源码分析

参考下一篇

Clone this wiki locally