支持 urp不_URP源码学习(七)一些细节和理解

URP主要的模块之前都看了一遍,URP也在不断更新,只看一遍还是不够的,之后会逐渐深入一些细节,以及跟着URP更新学一些新的东西。


RT理解

RT是什么,用在哪

  • 首先rt是一张特殊贴图,这张贴图对应的是GPU上的FrameBuffer,一般用到的是颜色和深度,从这张图取数据用于计算,或是直接对这张图进行修改,以得到想要的效果。
    • FrameBuffer就是gpu里渲染结果的目的地,我们绘制的所有结果(包括color depth stencil等)都最终存在这个这里。现代GPU通常都有几个FBO,实现双缓冲,以及将渲染结果保存在GPU的一块存储区域,之后使用。
  • RT的应用主要是几个方式,一是从rt取数据,比如取深度用于各种计算。二是取这张图,比如在UI上显示模型,或是截图保存等。再一个就是是对图进行处理,实现扭曲或是其他全屏效果。
  • 一般来说,不使用rt也是可以渲染出想要的图的,但是drawcall就会很多,unity内置管线,获取深度就是渲染一遍物体,这必然比直接取buffer消耗要大很多。但是从GPU拷贝数据回CPU,需要硬件支持,unity提供了CopyTextureSupport接口判断支持的拷贝方法,按硬件的发展速度应该不支持的会越来越少的。

unity接口

  • unity对rt的抽象是RenderTexture这个类,定义了一些属性,包括大小,精度等各种。
  • RenderTargetIdentifier
    • unity CoreModule实现,定义CommandBuffer用到的RenderTexture
    • 封装了texture的创建,因为texture创建方式有几种,rt,texture,BuiltinRenderTextureType,GetTemporaryRT
    • 这个类只是定义了rt的各种属性,真正创建应该是在CommandBuffer内部
    • BuiltinRenderTextureType类型:cameratarget、depth、gbuffer等多种
    • CommandBuffer.SetRenderTarget,可分别设置color和depth,以及贴图处理方式
    • CommandBuffer.SetGlobalTexture,效果是把texture赋值给shader变量,shader采样这个texture
  • RenderTextureDescriptor
    • 封装创建rt需要的所有信息,可复用,修改部分值,减少创建消耗
  • RenderTargetHandle
    • URP对RenderTargetIdentifier的一个封装
    • 保存shader变量的id,提升性能,避免多次hash计算
    • 真正用rt的时候,才会创建RenderTargetIdentifier
    • 定义了一个静态CameraTarget

URP用法

  • URP不会直接用到rt,而是通过CommandBuffer的接口设置,参数是RenderTargetIdentifier。
  • CoreUtils封装了SetRenderTarget方法,ScriptableRenderer调用
  • ScriptableRenderPass,封装ConfigureTarget方法,可以设置color和depth
  • pass设置好color和depth的rt后,renderer执行ExecuteRenderPass函数时读取,并设置给cb
  • pass内部会根据需要设置color和depth的渲染内容,比如从buffer拷贝深度时,是渲染深度值到color缓冲区。
  • 总结下来是由pass决定要渲染到哪个rt,以及用什么方式。然后renderer调用CoreUtils设置,设置好后调用pass的Execute方法渲染。

RT应用

深度纹理获取

URP提供了两种获取深度图的方法,一种是像内置管线那样,直接渲染指定pass,另一种是取深度buffer,渲染到一张rt上,优先用取深度buffer的方法,效率更高,但是需要系统和硬件支持。

先看下什么情况会生成深度图

  1. 主动开启,在PipelineAsset选择DepthTexture。
  2. 渲染scene相机,固定开启,并用DepthOnly的方式获得。
  3. 对于game相机,后处理,SMAA抗锯齿,DOF,运动模糊,用到了一个就会自动开启。判断在UniversalRenderPipeline的CheckPostProcessForDepth方法。

取深度buffer,CopyDepthPass

  • CanCopyDepth函数判断当前环境是否可开启。现在看起来需要系统支持拷贝深度贴图并且不能开启MSAA,看注释之后的版本会支持MSAA。
  • 这个pass一般在不透明渲染之后执行。看代码对scene相机执行时间不同,可是现在scene不会用这个渲染,可能是给以后留的吧。
  • 实现方法
    • SetUp:设置源rt关联到shader的_CameraDepthAttachment。目标rt关联到_CameraDepthTexture。
    • Configure:设置目标rt格式,colorFormat为Depth,32位,msaa为1不开启,filterMode为Point
    • Execute,这地方理解的不知道对不对
      • 先将源rt的内容赋值到shader定义的_CameraDepthAttachment贴图中
      • 然后调用基类的Blit方法,先设置管线的color为depth,也就是将depth渲染到color buffer中,然后执行Blit指令,用CopyDepth shader将buffer渲染到指定贴图上,后续shader直接采样这张贴图。
      • vert函数,坐标转换,object-clip,实际是没用的,有用的操作是设置uv,用于采样buffer,实际uv应该就是对应分辨率的。
      • frag:定义了msaa的处理,现在不会用到。直接采样_CameraDepthAttachment输出颜色,按现在的写法,应该直接用_CameraDepthAttachment就行了。额外渲染一次,应该是为了msaa准备的。
      • 流程总结:先设置管线的color buffer为depth,将相机得到的深度渲染到_CameraDepthAttachment,再调用CopyDepth shader渲染到_CameraDepthTexture

DepthOnlyPass

  • 渲染所有shader中有DepthOnly pass的物体到指定深度buffer。
  • 相机的rt,设置为哪个texture,渲染的物体就都渲染到这个rt上。

RT应用-opaque纹理获取

这个在内置的管线,是通过shader的grab指令获取的,移动设备支持的不好,URP加了一个拷贝buffer的方式,性能会好一些。

通过CopyColor pass实现。相比深度纹理简单很多,不需要判断硬件是否支持。

ForwardRenderer对depth和opaque贴图处理流程

  • renderer类相当于pass和unity底层交互的一个接口,定义了各个opaque和depth的rt
  • 各个rt默认是相机目标,可用于获取color和depth的buffer
  • 如果需要渲染color或depth到贴图中,在添加pass之前要做一些操作,只有base相机才能渲染到color和depth
    • 判断createColorTexture和createDepthTexture,设置m_CameraColorAttachment和m_CameraDepthAttachment
    • 如果需要创建texture,执行CreateCameraRenderTarget函数,这个函数会调用GetTemporaryRT生成rt,函数执行后,color的depthBufferBits可能会设置为32位。
    • 设置好后,会传给基类的m_CameraColorTarget。每个pass执行Execute方法前,会先设置camera的rt。

对rt的理解大概就这些,URP做了一些封装,看起来有点绕,反正核心就是改变渲染数据写入的位置,由屏幕变成我们定义的一张图,然后取这张图用来实现各种效果。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值