unity urp管线 闪退_URP源码学习(三)渲染管线的默认实现,forward

本文深入解析Unity URP的Forward渲染管线,包括核心部分Pass的配置和渲染逻辑,详细介绍了初始化、设置渲染目标、创建特殊材质、光源计算等关键步骤,帮助理解URP的内部实现。
摘要由CSDN通过智能技术生成

整体理解

这部分算是URP的核心了,可编程管线,说的就是这个,有能力的项目,可以根据需要,做出更适合项目的管线。

unity提供了两个默认实现,一个是forward,一个2D,2D有时间再细看(原谅我的懒),forward这部分还是有些东西可看的,因为默认管线,这部分是完全看不到的,只能通过framedebugger看个流程,现在有机会看看内部实现,对理解管线也是很有好处的。


核心部分,pass

ForwardRenderer可以简单理解成驱动各个pass执行的一个管理者,pass则实现了具体的渲染逻辑。

pass的功能,分为两部分,配置rt和执行最终渲染。

pass-事件

基类文件中定义了一系列的渲染事件,RenderPassEvent。每个pass,在初始化的时候,都定义了一个event,这个event用于pass的排序。id之间间隔50,可加offet以添加额外的event。

pass-配置rt

pass在渲染前需要先配置渲染目标,renderer基类调用pass的Configure抽象函数。

renderPass.Configure(cmd, cameraData.cameraTargetDescriptor); 

每个pass实现具体逻辑,pass子类调用基类的ConfigureTarget方法,配置渲染目标和clear方法,子类没实现则渲染到相机的目标。

渲染目标分两个,color和depth,depth只有一个,color是个数组,默认第一个是相机目标,最大值在SystemInfo.supportedRenderTargetCount定义。

注意这个步骤只是设置了pass内部的数据,并没有真的通知到管线。

RenderTargetIdentifier[] m_ColorAttachments = new RenderTargetIdentifier[]{BuiltinRenderTextureType.CameraTarget}; 
RenderTargetIdentifier m_DepthAttachment = BuiltinRenderTextureType.CameraTarget; 

真正设置渲染目标,是通过CommandBuffer的SetRenderTarget方法,URP在CoreUtils类封装了一个静态函数SetRenderTarget。ScriptableRenderer类在ExecuteRenderPass方法中,先调用pass的Config函数,然后取pass的color和depth数据,设置为真正的渲染目标。

梳理一下这个流程

787bbf0cf8e9fc8b7cfe375e29f8b71d.png

forward逻辑

forward-初始化

做了以下几件事

  • 创建几个特殊材质,用的是配置里的shader,这几个材质会传给对应的pass。
Material blitMaterial = CoreUtils.CreateEngineMaterial(data.shaders.blitPS); 
Material copyDepthMaterial = CoreUtils.CreateEngineMaterial(data.shaders.copyDepthPS); 
Material samplingMaterial = CoreUtils.CreateEngineMaterial(data.shaders.samplingPS);
Material screenspaceShadowsMaterial = CoreUtils.CreateEngineMaterial(data.shaders.screenSpaceShadowPS); 
  • 设置模板测试StencilState结构体。
  • 创建用到的每个pass,指定渲染RenderPassEvent。
  • 设置各个rt
  • 创建ForwardLights实例,用于光源的相关计算。
  • 创建RenderingFeatures,这个类里只有cameraStacking一个bool值,像是个没开发完的功能。

forward-Setup

简单说这个函数的作用就是把一个个pass加到个list里,供后边执行每个pass。

对于只渲染深度的相机,只需要添加3个pass,opaque、skybox、transparent。

一些重要的判断

  • 后处理是否开启,URP把后处理分成了两步,一个是实现常规特效的后处理,一个是抗锯齿这种,具体逻辑在PostProcessPass内部区分。
  • 是否需要深度图。首先判断相机配置,然后区分scene和game相机,scene相机之外,检测一下是否可以从opaque pass拷贝过来,以提升性能。具体判断在CanCopyDepth函数。

对一些特殊pass的说明,按代码顺序,没有特殊操作的略过

  • DepthOnlyPass
    • 开启条件:scene相机一定开启。game相机首先读取管线配置,同时CanCopyDepth为false,也就是说要注意本来不想开depth,但是开了抗锯齿等后处理效果,depth也会开启。
    • 用法:shader要有DepthOnly pass,渲染所有的DepthOnly Pass到指定texture,shader中通过_CameraDepthTexture获取。
  • CopyColorPass
    • 复制指定颜色buffer到目标颜色buffer,可以复制不透明物的渲染结果,用于扭曲特效。
    • 降采样可作为优化。
    • shader中通过_CameraOpaqueTexture获取。
  • CopyDepth和DepthOnly是互斥的,只需要用到一个,shader都是从_CameraDepthTexture获取。

其他pass还有很多 ,以后看shader的时候再一起细看。

ScriptableRenderer-Execute

unity把这部分放到了渲染管线的基类实现,也就是这部分被定义为通用的框架层,不建议项目扩展。

执行流程

  • 获取相机数据,关闭shader关键字,执行一次clear操作
SetCameraRenderState(cmd, ref cameraData); context.ExecuteCommandBuffer(cmd); cmd.Clear(); 
  • 对pass排序,按之前定义的RenderPassEvent。
  • 设置shader定义的时间变量,SetShaderTimeValues函数实现。
  • 将pass按event顺序,分成四块
    • BeforeRendering:用于处理阴影等,不是实际的渲染,只作为功能使用
    • MainRenderingOpaque:渲染不透明物体
    • MainRenderingTransparent:透明物体
    • AfterRendering:在后处理之后,在unity的demo中没看到具体渲染了啥,可能是扩展用的吧。
  • 执行SetupLights,设置光照需要的一系列参数,细节在光照部分细说。
  • 然后先执行BeforeRendering
  • 接着是一个循环,用于处理VR,由于手游中只需要渲染一次,VR部分先不管,只按一个去看。
    • 首先设置好相机属性,执行一次commandbuffer的clear指令。
    • 然后是不透明物体渲染,depth也在这执行。
    • 渲染透明物体,要注意的是透明和不透明物体的渲染,都是DrawObjectsPass实现的,参数不同,设置了RenderQueueRange和layer。
    • 渲染AfterRendering

forward大致流程大概就这些,写了好久,大量的细节都没细写,准备放到具体的pass里,结合shader和逻辑细看。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值