Unity URP UniversalRendePipeline

2024-02-01  本文已影响0人  暴走TA

简介: 感谢最近的工作需求,好好翻了一下 Unity URP UniversalRenderPipeline,继 URP 管线主要类 分析之后,来仔细看一下 UniversalRenderPipeline
软件: unity 2022.3.14f1c1
管线:com.unity.render-pipelines.universal@14.0.9

背景

由上篇文章 URP 管线主要类 分析之后 可知

  1. UniversalRenderPipeline 继承自 RenderPipeline
  2. UniversalRenderer 继承自 ScriptableRenderer
  3. UniversalRenderer 的数据类为 UniversalRendererData,用于保存 UniversalRenderer 的配置和创建 UniversalRenderer
    • UniversalRenderer 的构造函数强制需要传入 UniversalRendererData
    • UniversalRendererData 有一个 Create 函数用来创建 UniversalRenderer
  4. UniversalRenderPipelineAsset
    • 提供 UniversalRenderPipeline 的创建方法
    • 创建 UniversalRenderPipeline 时强制传入UniversalRenderPipelineAsset
    • 内部有一个 ScriptableRendererData 列表,用来保存当前管线可以用到的 RendererData , 然后还是用一个 ScriptableRenderer[] m_Renderers 来缓存生成的 scriptableRenderer
  5. URP 中的相机默认都必须有一个 UniversalAdditionalCamera 组件,这个组件保存了当前要用的 UniversalRenderer 的索引,提供一个 scriptableRenderer 属性用来获取当前相机的 Renderer。
    • scriptableRenderer 属性通过 UniversalRenderPipeline.asset 拿到管线配置文件,然后使用管线配置文件提供的 GetRenderer(int index) 方法获取对应的 scriptableRenderer。

Pipline 渲染步骤

除去我们不好找的引擎内部逻辑,我们就以引擎调用到 UniversalRenderPipelineRender(ScriptableRenderContext renderContext, List<Camera> cameras) 开始往后推。

Render 方法

  1. Pipline 的 Render,接受一个渲染上下文和一个相机列表。
  2. 开始部分会做一个 ProfilingScope 标记,然后设置一些色彩空间,渲染层级,MSAA 级别等。
  3. 遍历所有的相机
    • 如果是 Game 相机则调用 RenderCameraStack(renderContext, camera) 渲染。我们主要关注这个
    • 如果不是 Game 相机则再做一个 BeginCameraRendering 标记,然后更新 Volume框架,然后调用用 RenderSingleCameraInternal(renderContext, camera) 进行渲染。然后关闭标记
  4. 关闭对应的 ProfilingScope 标记

RenderCameraStack 方法

渲染 UPR 中的相机Stack

  1. 起手添加一个 ProfilingScope 标记
  2. 从相机对象上获取 UniversalAdditionalCameraData 组件,
    • 通过该组件就可以获得相机上的 scriptableRenderer
    • 通过该组件就可以获得相机上的 Stack 列表
  3. 遍历 Stack 列表,对相机数据进行预处理
    • 剔除已经删除的或未激活的相机,
    • 剔除和base相机不是同一个 scriptableRenderer 类型的相机
    • 收集堆中的相机是否有开启后处理的
  4. 结束 Stack 列表的遍历后,如果有相机不生效了,则更新相机的 stack
  1. 然后引入了 XRSsytem 系统, 向baske相机添加至其中,我不做 AR VR 所以,这里对我意义不大,当然 base 相机之后也是从这里取出,这里的放入、取出,我就当其没有发生过,管线这里这样写应该也是为了兼容 AR VR
  1. InitializeCameraData 方法初始化相机数据到 baseCameraData ,具体内容下面单写
  2. InitializeAdditionalCameraData 方法初始化相机数据到 baseCameraData , 具体内容下面单写
  3. 设置 baseCameraData 的一些属性
  4. RenderSingleCamera 调用单相机渲染 basecamera
  5. 遍历 cameraStack ,每个相机调用 RenderSingleCamera 进行渲染
    • 获取 cameradata
    • 调用 InitializeAdditionalCameraData 初始化 overlayCameraData
    • 设置 overlayCameraData
    • 调用 RenderSingleCamera 逐相机渲染
  6. 一些其它 XR 的设置和调用
    上述的步骤中基本上每个相机都会一个 ProfilingScope 标记对,用来便于debug,辅助功能所以没有全部写在上述的步骤中

InitializeCameraData

顾名思义,初始化相机数据。这个方法会将数据返回给传入的 cameraData 对象,InitializeAdditionalCameraData 也是这个操作。

  1. 设置 cameraData 的一些属性
    • 创建 cameraData 对象
    • 调用 InitializeStackedCameraData 初始化相机堆栈数据
    • 设置 cameraData.camera
    • 设置相机的 MSAA、 XR 、HDR、cameraTargetDescriptor信息
  2. 设置相机的堆栈数据 InitializeStackedCameraData
    • 设置 cameraData.targetTexture
    • 设置 cameraData.cameraType
    • 根据相机类型设置 环境和后处理设置,主要分为,场景相机数据、UPR的baseAdditionalCameraData数据、默认相机数据
    • 设置输出设置,HDR 、size、renderScale、upscalingFilter、imageScalingMode、fsrOverrideSharpness、defaultOpaqueSortFlags、captureActions

InitializeAdditionalCameraData

初始化 additionalCameraData 相机数据到 cameraData ,这里的 cameraData 和 InitializeCameraData 里的是同一个对象(结构体 struct)

  1. 设置 cameraData 的各种属性对象
    • 具体的属性对象就翻一下类看吧,就是相机场景的属性
  2. 设置一些 debug 属性的 override
  3. 设置了 SetViewProjectionAndJitterMatrix

RenderSingleCamera

主要的渲染逻辑在这里,主要是对renderer的设置,从这里也可以看出,我们的 UniversalRender 是和相机一一对应的,这个 renderer 对象就保存为 CameraData 的 renderer 属性,即 cameraData.renderer

  1. 设置从 cameraData 获取 renderer 和 camera
  2. ScriptableRenderer.current=renderer ; 进行全局设置。ScriptableRenderer.current 是一个静态属性
  3. CommandBufferPool 里获取一个 CommandBuffer cmd
  4. ProfilingScope 标记
  5. 调用 renderer.OnPreCullRenderPasses函数
  6. 计算一次 cmd ,context.ExecuteCommandBuffer(cmd)
  7. 设置相机相关的 shader 全局变量
    • 环境色
    • 环境光 等
  8. 一些特殊相机的预处理,如 CameraType.Reflection、CameraType.Preview、SceneViewCamera
  9. cameraData 设置 MotionVector 相关
  10. cameraData 设置相机输出 Handle 的尺寸
    11.context 获取剔除结果
  11. renderer 初始化 RenderingData
  12. renderer 添加渲染Pass
  13. 判断是否使用 useRenderGraph
    • 使用 则调用RecordAndExecuteRenderGraph 和 renderer.FinishRenderGraphRendering
    • 不使用则调用 renderer.Setuprenderer.Execute* ,我们一般的渲染都在 renderer.Execute 里面执行
  14. 结束标记
  15. context.ExecuteCommandBuffer(cmd) 执行 cmd,结束

流程完成

基本上上面的步骤走完,就开始使用 相机的 Renderer 进行渲染了。
在 pipeline 中主要做的就是,

上一篇下一篇

猜你喜欢

热点阅读