美文网首页
Unity URP 管线主要类之间的关系梳理

Unity URP 管线主要类之间的关系梳理

作者: 暴走TA | 来源:发表于2024-01-28 17:43 被阅读0次

简介: 最近有一个功能要修改管线,引擎没有人手,那就只能靠自己了,个人是很不喜欢改内置的东西的,不过迫不得已也得干呀,既然要改,甭管该多少,先抽点时间梳理一下 URP(SRP) 的来龙去脉。
软件: unity 2021.3.21f1c1
管线:com.unity.render-pipelines.universal@12.1.7
还额外获得了一个看类的好工具-VS的类设计器,下面也会附上用法

类设计器的安装与使用

打开安装工具
单个组件,类设计器安装

在一个类上右键 选择查看类图,便可以查看,可以同时多选多个类进行查看,在类图上右键也可以添加基类和派生类到视图中,可以一键排布布局


查看类图
类图关系

结构梳理

首先看一下几个基类

render和data类
主要涉及四个类
RenderPipelineAsset、RenderPipeline、scriptableRendererData、ScriptableRenderer
从名字可以看出
  1. RenderPipelineAsset 和 RenderPipeline 应该是一对儿,我们简称为管线对儿
  2. ScriptableRendererData 和 ScriptableRenderer 是一对儿,我们简称其为渲染对儿
    其中 RenderPipelineAsset 为管线对儿的数据文件,ScriptableRendererData 为渲染对儿的数据文件

分对儿看

管线对儿 RenderPipelineAsset 和 RenderPipeline

  1. 先看 RenderPipelineAsset ,启用 URP 管线必要的配置文件,可简单理解为,URP 就从这里开始(在这之前可能还有其它方法来调用,但我们可以先找一个简单的头) 。
    其中的 RenderPipelineAsset 就是我们使用 URP 管线时首先要创建的管线资源文件,所以他的主要功能就是用来存储管线需要用到的数据和配置

    PipelineAsset文件
    设置管线Asset文件后,我们的 URP 管线就正式激活了
    RenderPipelineAsset
    是一个抽象类,主要有四个方法 CreatePipleline、OnDisable、OnValidate、RenderPipelineAsset(构造函数),属性就是一些类似配置的属性。通过方法可以看出,RenderPipelineAsset 的主要目的就是使用其保存的数据和配置创建对应的 RenderPipeline 管线。
    默认 URP 自带一个 RenderPipelineAsset 的派生类UniversalRenderPipelineAsset ,这个就是我们实际使用的管线Asset文件。我们要写自己的管线,那么我们的Asset文件也需要派生自 RenderPipelineAsset
  2. UniversalRenderPipelineAsset
    默认 URP 的管线数据资源类,他有一个自己的 Editor界面绘制类 UniversalRenderPipelineAssetEditor。界面如下

    URP Asset
    主要包含渲染设置,质量设置,灯光设置,阴影设置,后处理设置。
    可以看出,这个类就是用来配置我们渲染管线的相关设置的。
    • 提供了右键菜单创建 UniversalRenderPipelineAsset 文件的功能,在创建的过程中还会自动创建一个 ScriptableRendererData 对象并保存为Asset文件,这个文件就是用来后期生成 ScriptableRenderer 用的。
    • 包含一个 UniversalRenderData 的对象列表,用来生成和设置相机的 ScriptableRenderer。
    • 以属性的形式保存了管线需要的一些默认材质球
    • 提供通过索引来获取 ScriptableRenderer 的方法 GetRenderer
  3. RenderPipeline
    RenderPipeline 这是个抽象基类,和 RenderPipelineAsset 是对应的,主要提供了一些约定方法。

    RenderPipeline 抽象类
  4. UniversalRenderPipeline
    UniversalRenderPipeline 是 unity 默认带的一个 URP 的 RenderPipeline 派生类,如果我们没有自定义过其它 RenderPipeline 那应该只有这一个具体实现类。它是通过 UniversalRenderPipelineAsset 的 (protected) CreatePipeline 方法来创建的。
    UniversalRenderPipeline 的构造函数默认强制传入一个 UniversalRenderPipelineAsset 对象,原因就是 UniversalRenderPipeline 需要使用 UniversalRenderPipelineAsset 里面的数据和配置生成正确的 Pipeline

    包含的方法
    • 这个类就具体的负责了渲染的流程,例如相机的设置,相机的排序,相机的堆栈渲染,灯光的处理,渲染的调用,等等
    • 这个类在 URP 的默认源码中的一处调用是 UniversalRenderPipelineAsset 的 scriptableRendererData 属性,这个属性用来获取默认材质和获取 ScriptableRendererData ,其 get 方法调用了 CreatePipeline();。
    • 另一处就是 UniversalRenderPipelineAsset 的基类 RenderPipelineAsset 约定的 (internal) InternalCreatePipeline 中调用了 抽象方法 CreatePipeline(),这个方法在 UniversalRenderPipelineAsset 进行了实现。

渲染对儿 ScriptableRendererData 和 ScriptableRenderer

与 RenderPipelineAsset和 RenderPipeline 关系类似,ScriptableRendererData 是一个数据配置存储文件,用来生成 ScriptableRenderer 对象。UniversalRenderPipelineAsset 对象内部用一个 ScriptableRendererData[] 数组来保存不同的 ScriptableRendererData 对象

  1. 先看 ScriptableRendererData
    一个可以序列化保存的对象,主要包含一个 RenderFeatures 列表,公用方法就一个 SetDirty() ,还一个保护类型的 Create 抽象方法,用来创建 ScriptableRenderer 。
    结构很简单,大体意思应该就是约定,renderdata 内需要保存 RenderFeatures ,然后派生类需要实现 Create()方法用来创建对应的 ScriptableRenderer 对象
    ScriptableRendererData
  2. UniversalRendererData
    引擎默认派生了三个 data 类 Renderer2DData、ForwardRendererData、UniversalRendererData,其中的 ForwardRenderer 是一个被舍弃的 Renderer,被UniversalRendererData代替。
    每一个data派生类,内部都有一个 ShaderResources 类,用来保存当前管线需要的一些 shader 路径。
三个data派生类

UniversalRendererData 有一个专门的 UniversalRendererDataEditor 类来绘制其 Inspector 界面


UniversalRendererData 界面

可以看到,基本包含了一些具体的渲染设置,还有基类约定的 Feature 对象。
* 实现了基类的 Create() 方法,用来创建对应的 ScriptableRenderer
* 包含渲染排序,渲染路径的设置,后处理等渲染选项的设置,和 UniversalRenderPipelineAsset 不同的是,UniversalRenderPipelineAsset 的设置大部分是关于,整套管线的流程类型的,UniversalRendererData 则侧重于具体的渲染开关,和 pass 设置。 也就是 UniversalRendererData 负责的是 UniversalRenderPipelineAsset 负责的整个管线中渲染的一小部分。所以 UniversalRenderPipelineAsset 里面是有一个 UniversalRendererData 列表的。

  1. ScriptableRenderer
    一个抽象类,使用 ScriptableRendererData 的配置数据,通过ScriptableRendererData 的 Create 方法进行创建其派生类。
    • 包含大量的渲染开关和属性,用来做具体渲染时的控制
    • 构造函数必须包含 ScriptableRendererData 对象,确保生成的 renderer 的正确性
    • 主要针对相机的渲染操作,例如,设置渲染target,设置 culling 参数,设置灯光,设置渲染前的pass 等
  2. UniversalRenderer
    ScriptableRenderer 的派生数量与 ScriptableRendererData 的数量 一 一 对应。
    三个renderer派生类
    • UniversalRenderer 的方法与基类方法基本一致,大部分都是覆写。
    • 主要用来处理渲染时,渲染对象,渲染状态等的控制
    • 内部持有大量的 ScriptableRenderPass(抽象类)的派生类,用来处理渲染效果。
    • 持有大量的渲染材质,用来处理渲染效果。
    • 持有大量的RTHandle ,用来处理渲染输出。
    • 所以 UniversalRenderer 是我们应用到的最多的渲染类。


      内部持有的大量渲染用对象

扩散

上述几个类的相互关系

  • RenderPipelineAsset 生成 RenderPipeline,RenderPipeline 用来控制管线的渲染流程
  • RenderPipelineAsset 包含 ScriptableRendererData 列表
  • ScriptableRendererData 生成 ScriptableRenderer , ScriptableRenderer 用来控制渲染指令和状态

UniversalAdditionalCameraData

RednerPipeline 咋调用的 ScriptableRenderer 呢
在上面的代码分析中,我们并没有找到直接的调用关系

  • 引擎在切换到 URP 管线后,我们会注意到,相机上会新增一个 UniversalAdditionalCameraData 组件,这个组件内部的一个共有属性 scriptableRenderer 它通过相机上设置的 renderer 的索引,使用 UniversalRenderPipeline.asset.GetRenderer(defaultIndex); 来获取当前相机的 ScriptableRenderer 。

  • 在 UniversalRenderPipeline 的 InitializeAdditionalCameraData 方法执行时,将 ScriptableRenderer 包装进了 CameraData,所以在 pipeline 的执行过程中,大部分情况下可以通过 CameraData 来获取 ScriptableRenderer ,对应的属性名为 renderer
    cameraData.renderer = asset.scriptableRenderer;

  • 所以之前也说 ScriptableRenderer 是针对与相机渲染的

ScriptableRenderPass

  1. 主要用于实际的渲染操作,大部分存在于 RenderFeature 和 ScriptableRenderer 中。
  2. ScriptableRenderer 中包含了 m_ActiveRenderPassQueue 队列,Feature 内的 pass 也通过遍历的形式被添加进 m_ActiveRenderPassQueue
  3. 渲染操作遍历 m_ActiveRenderPassQueue 进行渲染状态的操作与渲染
  4. 所以 ScriptableRendererFeature 可以实现类似旧管线中的多 pass 渲染

ScriptableRendererFeature

  1. ScriptableRendererData 内包含 ScriptableRendererFeature 列表
  2. 在生成 ScriptableRenderer 的时候会将 ScriptableRendererData 内的 ScriptableRendererFeature 传递到 ScriptableRenderer 的 m_RendererFeatures 内。
  3. 在 ScriptableRenderer 抽象类内,需要调用的地方以遍历的形式进行调用,例如 AddRenderPasses、OnPreCullRenderPasses、Dispose 等
  4. ScriptableRendererFeature 的派生类内基本都会包含一个 renderObjectsPass,通过前几步的调用关系,便可以将当前的feature的pass 传递到 Renderer 的渲染过程中。
  5. ScriptableRendererFeature 内可以包含各种设置属性,用来设置其内部将要参与渲染的 ScriptableRenderPass

结束

基本结构和相互关系,大致如此,主要的就是先了解四个基类的关系,然后是其派生类


四个大类

然后就是四大类中主要用到的几个类


相关类
至于具体的派生类,有时间慢慢了解即可

相关文章

网友评论

      本文标题:Unity URP 管线主要类之间的关系梳理

      本文链接:https://www.haomeiwen.com/subject/xgsvodtx.html