unity生成预制体_[Universal RP]Unity通用渲染管线学习

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第1张图片

Unity正式加入了Universal RP(通用渲染管线),这里会记录一些官方文档,并分析管线的代码,文中使用Unity2019.3.0b1,Universal RP 7.0.1。

可编程渲染管线

为了解决仅有一个默认渲染管线,造成的可配置型、可发现性、灵活性等问题。Unity在管线设计的概念上做了转移,决定在C++端保留一个非常小的渲染内核,让C#端可以通过API暴露出更多的选择性,也就是说,Unity会提供一系列的C# API以及内置渲染管线的C#实现;这样一来,一方面可以保证C++端的代码都能严格通过各种白盒测试,另一方面C#端代码就可以在实际项目中调整,有任何问题也可以方便地进行调试。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第2张图片

新的管线对用户而言主要是C# 端的API以及由这些API编写的一系列定制化的内置渲染管线。而在内部实现上,引擎C++端会负责多线程实现性能关键的部分,如上图所示,而C#端负责更高层的渲染指令调度。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第3张图片
可编程渲染管线的使用层设计

用户可以直接使用开源的内置管线,或者在内置管线的基础上进行修改,甚至直接编写定制化的管线。具体使用上渲染管线在工程中会生成特定的Asset,如下图所示,这个Asset序列化了这条管线的一些公共设置变量,并负责在运行时创建实际的渲染上下文;当这个Asset的设置变量在运行时发生变化,引擎会销毁当前上下文然后重新创建管线。

可编程渲染管线是URP的基础,通过它我们可以知道unity中怎么实现最基本的渲染,unity对渲染管线API封装程度。

详解可编程脚本渲染管线SRP - Unity Connect​connect.unity.com
unity生成预制体_[Universal RP]Unity通用渲染管线学习_第4张图片
Scriptable Render Pipeline Overview – Unity Blog​blogs.unity3d.com
unity生成预制体_[Universal RP]Unity通用渲染管线学习_第5张图片

通用渲染管线Universal RP

LWRP是URP之前的名称,两者基本没有区别,URP相对LWRP的变化主要是把PostProcessing集成到内部了。

Unity轻量级渲染管线LWRP源码及案例解析(上) - Unity Connect​connect.unity.com
unity生成预制体_[Universal RP]Unity通用渲染管线学习_第6张图片
Unity轻量级渲染管线LWRP源码及案例解析(下)​connect.unity.com

Unity轻量级渲染管线LWRP源码及案例解析,讲解了URP的使用方法和拓展方法,里面有对SRP、URP的一些说明,URP与内置管线的对比,URP的源码结构。

在继续看源码细节之前,先看看URP的主要提升(相对于内置管线),和不完善的地方。

提升:

1 开源

可编程渲染管线最大的好处就是开源,对于有能力的团队,可以选择在SRP的基础上写自己的管线。而使用Unity提供的管线模板URP或HDRP,也可以把他们从Package包中提出到Asset中做更改,上面的文章有提到修改的注意事项(其实就是记着把Shader中的include路径,和代码中的Shader.Find之类的路径改一下),但是并不推荐这么做,因为版本更新的维护是噩梦。开源意味着容易定位到问题,对调试非常友好。

2 渲染路径改为单Pass Forward Rendering

内置管线的多Pass Forward Rendering,会在多光源时对额外的光源使用新的FowardAdd Pass计算,Pass数量是影响物体的光源数量,最大值为8。

URP的单Pass Forward Renderering,会将光源一次性传入Forward Pass,但由于单Pass能够传的数据有限,现在最多支持一个直线光外加4个其他光源。

这样做虽然并不完美,但多光源场景中DrawCall数量会大量下降。

3 拓展性(非代码修改)

URP在渲染队列中嵌入了拓展入口,相当于之前的CommandBuffer的可视化操作。上面的文章中有详细的使用方法。

用新的设计取代了GrabPass的结构,在Opaque渲染之后可以截出一张RenderTexture,提供给之后使用。

4 SRP Batcher

提供了一种新的批处理方式,基于Shader的批处理。不过这个技术还不是正式功能,有些局限,不支持Skinned Meshes、Material Property Blocks。

缺点:

1 不支持多相机叠加

这是很重要的功能,如果真用到了,就去改源码吧,要不等之后更新。

2 Defferred Renderring

现在URP里面没有延迟渲染,也没有时域抗锯齿TAA。

一个SRP代码示例

我们先看 详解可编程脚本渲染管线SRP - Unity Connect 中的最后一个例子,半透明渲染。

using 

渲染入口点为RenderPipeline类中的Render函数,参数为相机列表和渲染上下文,在这个函数的最后提交渲染上下文,完成渲染。填充渲染上下文的过程中,Unity封装好了一些方法,包括剔除操作、CommandBuffer的一系列指令、绘制渲染器等。

Universal RP

推荐先熟悉Universal RP的使用,再去看代码的实现,这样效率会更高。

Universal RP 7.0的文档​docs.unity3d.com

Universal RP的依赖Package有两个,CoreRPLibrary是URP和HDRP都用到的一些工具,ShaderGraph是shader的可视化节点编辑器,之前的PostProcessing已经集成到内部了。

e377fee54addca04d28a6800fdedc918.png

2c6ca929495b04ccbd4ccb2f1122a1c9.png

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第7张图片

Render方法

Universal RP的主要实现就在Universal RP的Runtime文件夹中,我们从渲染入口点开始看实现细节。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第8张图片
UniversalRenderPipeline类中的Render方法

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第9张图片
一个Rendering Loop过程

整体结构非常简单,设置GraphicSetting参数,设置每帧Shader中的Global 变量,相机排序,相机遍历,每相机渲染。

首先看一下四个方法BeginCameraRendering、BeginFrameRendering、EndCameraRendering、EndFrameRendering,它们是基类RenderPipeline中的渲染管线回调。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第10张图片
RenderPipeline

GraphicsSettings.lightsUseLinearIntensity = (QualitySettings.activeColorSpace == ColorSpace.Linear);

更改颜色空间设置,这个设置位置在Player的OtherSetting中

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第11张图片

GraphicsSettings.useScriptableRenderPipelineBatching = asset.useSRPBatcher;

是否开启SRPBatcher(根据shader合并材质),这个功能使用还需要在Shader中将需要用CBuffer保存的变量用一段代码包含。并且有一定的限制。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第12张图片
按材质合并与按Shader合并

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第13张图片
SRPBatcher使用注意事项

asset是指UniversalRenderPipelineAsset生成的管线资源,上面包含许多可调节设置,如SRPBatcher在倒数第四行,其他设置会在用到时说明。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第14张图片
UniversalRenderPipelineAsset中的设置

SetupPerFrameShaderConstants函数

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第15张图片

RenderSettings.ambientProbe是环境光的2阶球谐函数表达,Unity也使用SphericalHarmonicsL2存储LightProbe数据。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第16张图片
RenderSettings.ambientProbe在这里设置

将系数转到相应颜色空间,把参数-环境光颜色、Subtractive模式下的阴影颜色传递到Shader,这就是每帧的shader常量。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第17张图片
PerFrameBuffer

PerFrameBuffer类中的参数是每帧需要的数据缓存,这些静态数据在创建管线时(或修改管线参数时)被赋值。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第18张图片
UniversalRenderPipeline的构造函数

继续看Render函数中的SortCameras(cameras)

799394cff78f27565a2bb0df1c9153ea.png
按深度排序

接下来是遍历相机,我们先不关心VFX.VFXManager.ProcessCamera(camera)函数,它是为了在管线中集成Visual Effect Graph功能使用的,这里只有一个需要关心的方法RenderSingleCamera(renderContext, camera)。

RenderSingleCamera方法

public 

这个方法的过程如下:

  1. 初始化剔除参数
  2. 获取UniversalAdditionalCameraData
  3. 初始化CameraData
  4. 设置PerCameraBuffer(每相机使用的Shader Global变量PerCameraBuffer)
  5. 获取ScriptableRenderer
  6. 使用ScriptableRenderer继续填充剔除参数和CameraData
  7. 开始性能采样(Profiler面板)
  8. 编辑器模式下Scene相机额外显示UI
  9. 剔除
  10. 根据管线设置、CameraData、剔除结果,初始化渲染数据RenderingData
  11. 使用ScriptableRenderer根据RenderingData,Setup并Excute渲染上下文
  12. 结束性能分析
  13. 提交渲染上下文

1 初始化剔除参数

camera.TryGetCullingParameters(IsStereoEnabled(camera),outvar cullingParameters)用于获取剔除结果,IsStereoEnabled是判断是否是立体相机(VR/AR)。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第19张图片

2 获取UniversalAdditionalCameraData

获取摄像机的额外数据UniversalAdditionalCameraData,我还没搞懂为什么面板是空的,里面的数据能序列化,甚至还有Tooltip,估计是没开发完。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第20张图片
挂着Camera所在GameObject上,面板默认不暴露

3 初始化CameraData,InitializeCameraData方法

static 

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第21张图片
CameraData类

详细的设置大家阅读代码就可以得知。关于if(additionalCameraData !=null)那段设置,我没理解,现在的状态就是不添加UniversalAdditionalCameraData就会不支持后处理等效果,这里猜测这个设计的目的是为了区分两种相机模式,还希望大家能告诉我为什么。defaultOpaqueSortFlags的两种情况只差了一个是否按深度排序,其中camera.opaqueSortMode并没有被设置,在URP中始终未OpaqueSortMode.Default。captureActions只在Editor模式下生效,是录屏用的。cameraTargetDescriptor是RenderTextureDescriptor,在之后的Blit等操作里会用到,MSAA值也保存在这里。

4 设置PerCameraBuffer

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第22张图片
SetupPerCameraShaderConstants方法

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第23张图片
PerCameraBuffer类

这里设置的几个摄像机参数,_ScreenParams的4个向量格式在HLSL或者GLSL都会用类似的方法传递。

98d9ca8a30fcb6ba60aed4a5d84d2495.png
乘法顺序与命名顺序

读到这里,我对乘法顺序有疑问,于是去找shader中的乘法使用,以对比C#中的参数。

9f8f6e527daf4fb1536f9ae84321479c.png

7bc5ccbae7bff6fa25f498bf160feffa.png
com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl中的本地坐标转为世界坐标

首先注意shader中通常使用矩阵在左向量在右的常规乘法。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第24张图片
com.unity.render-pipelines.universalShaderLibraryInput.hlsl

注意红框中,UNITY_MATRIX_MV实际是UNITY_MATRIX_V × UNITY_MATRIX_M。矩阵乘法满足分配率,MVP矩阵乘向量p,与P(V(Mp))是相等的。这也是为什么C#端VP = P×V,只是命名习惯的问题。

5 获取ScriptableRenderer

ScriptableRenderer renderer = (additionalCameraData != null) ? additionalCameraData.scriptableRenderer : settings.scriptableRenderer;

ScriptableRenderer是抽象出的渲染功能实体,是UniversalRP可拓展的最外层,里面还有ScriptableRenderPass可以拓展。目前Unity提供了2个实现ForwardRenderer和Renderer2D,管线默认使用ForwardRenderer,默认资源是UniversalRP/Runtime/Data/ForwardRendererData.asset。可以每相机使用不同的ScriptableRenderer,这个设置方法和版本有关,可以看这个版本使用的addtionalCameraData.scriptableRenderer,有的版本使用camera.scriptableRenderer。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第25张图片
使用Custom管线

6 使用ScriptableRenderer继续填充剔除参数和CameraData

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第26张图片
ScriptableRenderer.Clear

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第27张图片
ScriptableRenderer.SetupCullingParameters

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第28张图片
ForwardRenderer.SetupCullingParameters

ef61e5c477691a721258d80e83b96351.png
Renderer2D.SetupCullingParameters

Clear方法相当于ScriptableRenderer的每相机初始化,SetupCullingParameters是虚方法,在ForwardRenderer和Renderer2D中有不同实现,后面以ForwardRenderer为主进行说明,ForwardRenderer中SetupCullingParameters进一步确定了阴影距离。

7 开始性能采样(Profiler面板)

CommandBufferPool是CommandBuffer对象池,ProfilingSample是封装的性能采样器,这两个类都在Core RP的Package中。

8 编辑器模式下Scene相机额外显示UI

9 剔除

var cullResults = context.Cull(ref cullingParameters),剔除是Unity封装好的一个方法,我们只能通过参数设置进行控制。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第29张图片
剔除参数

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第30张图片
剔除结果的内容

10 根据管线设置、CameraData、剔除结果,初始化渲染数据RenderingData

static 

RenderingData是用于存储每相机渲染所需的所有数据的结构体,这个方法的目的就是完全填充渲染数据,最后交给ScriptableRenderer使用。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第31张图片
RenderingData结构体

var visibleLights = cullResults.visibleLights,从剔除结果中获得所有可见光GetMainLightIndex代码如下,可以从代码中看出MainLight的定义。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第32张图片
GetMainLightIndex方法

下面一段是MainLight和AdditionalLights是否存在阴影的判断,可以看出URP是不支持AdditionalLights的点光源和直线光源阴影的。CullResults和CameraData直接赋值给RenderingData。LightData、ShadowData和PostProcessingData方法由独立的方法赋值。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第33张图片
InitializeLightData方法

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第34张图片
最大AdditionalLight数量是4,每相机最大可见光数量是16

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第35张图片
LightData相关设置

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第36张图片
InitializeShadowData方法前半段

InitializeShadowData方法前半段,设置每光线的Bias值,这里UniversalAdditionalLightData和相机上挂的额外数据类似,不过这个脚本目前只有usePipelineSettings这一个字段,还是默认的true,面板同样是空的。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第37张图片
InitializeShadowData方法后半段

InitializeShadowData方法后半段,设置是否支持MainLight和AdditionalLights的阴影,用到了“MainLight和AdditionalLights是否存在阴影”数据,分别设置ShadowMap的尺寸,MainLight的阴影额外设置级联数据。设置是否支持软阴影、设置ShadowMap的DepthBuffer使用16bits数据。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第38张图片
ShadowData相关设置

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第39张图片
InitializePostProcessingData方法

2c6c8ff22c9780480d74aba7bfa1f444.png
PostProcessingData设置

supportsDynamicBatching:是否支持动态批处理。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第40张图片
PerObjectData枚举

PerObjectData是每Object需要的数据标记,通过下图方法获取。

7f6e769148c00b1b14a3a9cd3fb6c725.png

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第41张图片

killAlphaInFinalBlit会在最后的Blit操作前开启ShaderKeyword:_KILL_ALPHA,把前面的数据完全覆盖。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第42张图片
com.unity.render-pipelines.universalShadersUtilsBlit.shader的片元着色器

11 使用ScriptableRenderer根据RenderingData,Setup并Excute渲染上下文

在看具体实现之前,先看看ScriptableRender的设计。

ScriptableRender是由一个实体生成的——ScriptableRendererData。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第43张图片
ScriptableRendererData类

ScriptableRendererData中需要注意Create方法,它会在新建渲染管线时与管线一同创建,设置变化时重新创建ScriptableRender实例,还可以根据每相机设置来创建。ScriptableRendererData中的ScriptableRendererFeature集合,是URP提供给用户不用改代码就能增加Feature的功能,类似的,ScriptableRendererFeature继承自ScriptableObject,它可以创建出ScriptableRenderPass实例。

ScriptableRender类中定义了ScriptableRenderPass集合List m_ActiveRenderPassQueue = new List(32),ScriptableRenderPass中有抽象方法Execute,这个方法会在ScriptableRenderPass的不同子类中实现,context的渲染指令就是在ScriptableRenderPass.Execute方法中被填充的,比如context.DrawRenderers、context.DrawSkybox、context.ExecuteCommandBuffer等指令。ScriptableRenderer中的Setup方法会生成需要的m_ActiveRenderPassQueue,Excute方法会给m_ActiveRenderPassQueue排序分类、设置渲染目标、完成ScriptableRenderPass.Execute调用。

ce709f245f1de99d236b78d6dbffb278.png
ScriptableRenderPass.Execute

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第44张图片
ScriptableRender.Setup

ScriptableRenderer.Setup是虚方法。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第45张图片
ForwardRender类

ForwardRender类中定义了许多Pass结尾的变量,它们就是ScriptableRenderPass的子类。这里还有光照信息,光照在初始化和SetupLights方法中被赋值使用。

ForwardRender.Setup方法使用RenderData数据,来设置好渲染所需要的内容:管理并提交ScriptableRenderPass到m_ActiveRenderPassQueue;提前定义好这个相机要使用的颜色和深度目标,数据格式是RenderTargetIdentifier,是CommandBuffer中RenderTexture的标识;将RendererFeatures生成的ScriptableRenderPass添加到m_ActiveRenderPassQueue中;创建相机渲染目标的临时RenderTexture;设置Backbuffer的格式。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第46张图片
ForwardRender中初始化ScriptableRenderPass的过程

可以把渲染理解为绘制过程,这些ScriptableRenderPass子类就代表不同的过程,可以在上图中看到这些过程所处的阶段,即不同过程的绘制顺序。

  • VolumeBlendingPass:后处理使用的Volume融合,URP中作为第一个绘制使用
  • MainLightShadowCasterPass:主光源的ShadowCaster贴图绘制
  • AdditionalLightsShadowCasterPass:附加光源的ShadowCaster贴图绘制
  • DepthOnlyPass:绘制深度贴图
  • ScreenSpaceShadowResolvePass:使用ShadowCaster贴图和深度贴图绘制屏幕空间的阴影贴图
  • ColorGradingLutPass:绘制用于后处理ColorGrading的Lut贴图
  • DrawObjectsPass:绘制不透明物体或半透明物体,第一次使用处于RenderPassEvent.BeforeRenderingOpaques阶段,绘制不透明物体
  • CopyDepthPass:复制深度贴图
  • DrawSkyboxPass:绘制天空盒
  • CopyColorPass:复制颜色贴图
  • DrawObjectsPass:绘制不透明物体或半透明物体,第二次使用处于RenderPassEvent.BeforeRenderingTransparents阶段,绘制半透明物体
  • PostProcessPass:后处理,第一次使用处于RenderPassEvent.BeforeRenderingPostProcessing阶段阶段
  • PostProcessPass:后处理,第二次使用处于RenderPassEvent.AfterRenderingPostProcessing阶段阶段
  • CapturePass:用于RenderPassEvent.AfterRendering阶段的截屏,前面提到非Editor模式下renderingData.cameraData.captureActions是空的
  • FinalBlitPass:通常在没有后处理且不以相机为渲染目标的渲染中使用,比如RenderScale不为1时,用于把渲染结果重新传到屏幕

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第47张图片
ForwardRender.Setup第1段

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第48张图片
ForwardRender.Setup第2段

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第49张图片
ForwardRender.Setup第3段

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第50张图片
ForwardRender.Setup第4段

因为ScriptableRenderPass的子类内容比较多,这里不展开分析Setup方法了,先去看看ScriptableRender.Execute的功能。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第51张图片
ScriptableRender.Execute

ScriptableRenderer.Execute是ScriptableRenderer层的绘制执行方法,过程如下:

  • 清理光照与阴影的ShaderKeyword
  • m_ActiveRenderPassQueue按照ScriptableRenderPass.renderPassEvent排序
  • 时间设置与缓存
  • 按Block划分m_ActiveRenderPassQueue
  • 执行RenderPassBlock.BeforeRendering的Block
  • 初始化相机相关的属性(Shader变量)
  • 设置光照(SetupLights方法)
  • 时间设置为之前缓存值
  • BeginXRRendering
  • 执行RenderPassBlock.MainRendering的Block
  • 绘制GizmoSubset.PreImageEffects的Gizmos
  • 执行RenderPassBlock.AfterRendering的Block
  • EndXRRendering
  • 绘制GizmoSubset.PostImageEffects的Gizmos
  • 清理数据

时间的设置,官方还会改动,代码中有注释说明。有个block的概念,m_ActiveRenderPassQueue被分为3个block,按照下图节点划分,FillBlockRanges为划分方法,ExecuteBlock为按Block执行。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第52张图片
Block划分依据

ExecuteBlock方法中进一步调用了指定Block中的ExecuteRenderPass方法,ExecuteRenderPass方法在确定ScriptableRenderPass对应的渲染目标后,调用ScriptableRenderPass.Execute设置每个渲染模块的上下文。

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第53张图片
ScriptableRenderer.ExecuteRenderPass

下面通过Unity中的FrameDebug看看渲染目标设置的过程,Game视窗当前分辨率为1600*900。

  1. SetRenderTarget.Clear1——VolumeBlendingPass被视为第一个以相机为渲染目标的Pass,设置了一个1600*900的
  2. SetRenderTarget.Clear2——MainLightShadowCasterPass在Configure中重新定义了渲染目标,渲染目标变更为2048*1024的TempBuffer
  3. RenderMainShadowMap——在TempBuffer上绘制ShadowCaster,这里的两个绘制对应两个阴影级联
  4. SetRenderTarget.Clear——DepthOnlyPass在Configure中重新定义了渲染目标,渲染目标变更为1600*900的_CameraDepthTexture
  5. DepthPrePass——在_CameraDepthTexture中绘制深度信息
  6. SetRenderTarget.Clear——ScreenSpaceShadowResolvePass在Configure中重新定义了渲染目标,渲染目标变更为1600*900的_ScreenSpaceShadowMapTexture
  7. ResolveShadows——根据_CameraDepthTexture、TempBuffer在_ScreenSpaceShadowMapTexture中绘制阴影
  8. RenderOpaques——在上绘制不透明物体,使用到了_ScreenSpaceShadowMapTexture,这里出现了渲染目标变更,但变更目标是之前存在的,所以并没有创建渲染目标
  9. RenderSkybox——在上绘制天空盒

unity生成预制体_[Universal RP]Unity通用渲染管线学习_第54张图片
ForwardRender的一帧渲染

ExecuteRenderPass方法中有一行ClearFlag clearFlag = GetCameraClearFlag(camera.clearFlags),这个方法获取第一个Clear的ClearFlag,在不同平台上结果有差异,大家一定要注意。

12 结束性能分析

在ProfilingSample执行Dispose时cmd设置为结束性能分析,并立刻被提交到context中。

13 提交渲染上下文

context.Submit();


由于ScriptableRenderPass内容比较多,就不详细列出RenderData设置的参数是怎么作用于不同的ScriptableRenderPass了,可以在使用相应模块时再去了解。

之后会更新Universal RP中的Lit.shader的内容,这个Shader相当于默认渲染管线中的Standard.shader。

你可能感兴趣的:(unity生成预制体,unity透明通道加颜色)