ChuanXin 发表于 2021-11-21 15:34

【Unity Shader】Builtin升级URP学习笔记(二)

一、URP概要

通用渲染管线,URP(Universal Render Pipleline),在2019.3版本中,Unity将轻量渲染管线LWRP重命名为通用渲染管线URP,通用渲染管线是制作精美图形和显示效果的强力方案,并且同时支持多个平台。轻量渲染管线设计初时具有快捷、可伸缩的优点,可为所有移动端带来高质量的图形效果。


以下是应用阶段的渲染流程顺序:


内置渲染管线的缺陷
定制性差:过去,Unity有一套内置渲染管线,渲染管线全部写在引擎的源码里。大家基本上不能改动,除非是买了Unity源码客户,当然大部分开发者是不会去改源码,所以过去的管线对开发者来说,很难进行定制。
代码脓肿,效果效率无法做到最佳:内置渲染管线在一个渲染管线里面支持所有的二十多个平台,包括非常高端的PC平台,也包括非常低端的平台,很老的手机也要支持,所以代码越来越浓肿,很难做到使效率和效果做到最佳。
SRP诞生的目的
为了解决仅有一个默认渲染管线,造成的可配置型、可发现性、灵活性等问题。决定在C++端保留一个非常小的渲染内核,让C#端可以通过API暴露出更多的选择性,也就是说,Unity会提供一系列的C# API以及内置渲染管线的C#实现;这样一来,一方面可以保证C++端的代码都能严格通过各种白盒测试,另一方面C#端代码就可以在实际项目中调整。


二、URP和Builtin的对比

URP在性能上的优势

主要提速的有两个方面

[*]光照处理(包括阴影)
[*]SRP Bacher (SRP批处理)(重点)
渲染路径的差别
URP是单Pass前向渲染管线,而内置管线是多Pass前向渲染管线和延迟渲染管线。URP没有延迟渲染,因此我们只对比前向渲染这一项(手游基本只会用前向渲染,延迟渲染的G-Buffer所需要的带宽带来的开销太大)。
所谓的前向渲染,就是在渲染物体受点光光照的时候,分别对每个点光对该物体产生的影响进行计算,最后将所有光的渲染结果相加得到最终物体的颜色。
主要区别描述URP多Pass用多个pass来渲染光照,第一个pass只渲染主光源,然后多出来的光每个光用一个pass单独渲染。所以在这个管线不敢用多个动态光照,标准做法是烘培Lightmap。Builtin单Pass在一个pass当中,对这个物体受到的所有光源通过一个for循环一次性计算。URP这么做的好处有:

[*]一个物体的光照可以在一次DrawCall中计算完毕
[*]省去了多个Pass的上下文切换以及光栅化等开销
GrabPass
还有一个内置管线中,很难运用到手游中的技术,那就是GrabPass。
这个技术通常会用来制作空气扰动或者刀光等特效带来的折射效果,在内置管线中如果使用这个功能,则会在每个用到这个Shader的地方对屏幕缓冲区进行一次抓取操作, 这个操作会大幅消耗GPU的带宽。 在移动设备上带宽是非常有限的资源,因此这个效果在手机上几乎是没法使用的。
在URP中,可以在渲染管线的配置文件中,开启Opaque Texture,这张图是管线在完成不透明物体渲染后,将屏幕缓冲区中(也可能是相机的ColorRT)的颜色信息抓取出来保存到一张单独的RT当中,然后在特效中就可以直接拿这张图去进行扭曲和扰动计算。


这么做的好处就是可以将抓取操作的次数恒定下来,不会因为同屏有多少个需要扰动的对象而额外增加开销。当然坏处也比较明显,那就是没办法对不透明物体进行扰动操作了,也就是说只能对场景物件而没法对特效进行扰动。
URP在扩展性上的优势

Unity提出SRP,其中一个最大的初衷就是提高渲染管线的灵活性,给使用者提供最大的自定义空间来满足各个项目的需求。要想一个渲染管线满足所有类型项目的需求,这是不可能的,这必然会造成对性能或者功能上的妥协。
因此URP自然而然的具备了非常强大的可扩展性,其大多数功能都是完全模块化的,可以自由搭配组合,而且对她进行扩展大多数情况下是不需要修改URP本身源码的。
1.RenderFeature/RenderObject
这个功能是LWRP6.x之后加入的新功能,其中RenderObject是RenderFeature的一个默认实现,可以让大家在不写一行代码的情况下对渲染管线进行扩展。
2.ScriptableRenderer
URP对ScriptableRenderer进行继承,从而实现一个完全自己的Renderer,因此如果你足够强,完全可以自己写个延时渲染器出来,最棒的是,他已经实现的Pass可以随便抓来用,避免去写一些重复的东西。因此如果大家对管线中有任何不爽的地方或者觉得没必要的地方,大可自由裁切和扩展,自己的项目需要啥咱就用啥,不需要啥就砍啥,主动权完全抓在自己手里。
三、SRP Batcher

SRP Batcher是什么?
SRP Batcher 是一个底层渲染循环,可通过许多使用同一着色器变体的材质来加快场景中的 CPU 渲染速度。通俗来说,就算是不同的材质球,只要是用一个着色器变体的物体都可以批处理到一块。它的主要目的是减少渲染状态设置的开销,还有就是把物体属性用专用代码快速更新。
SRP Batcher是怎么优化的?
SRP Batcher使材质数据持久保留在 GPU 内存中。如果材质内容不变,SRP Batcher 不需要设置缓冲区并将缓冲区上传到 GPU。还有 SRP Batcher 会使用专用的代码路径来快速更新大型 GPU 缓冲区中的 Unity 引擎属性,如下图。


就是CPU不需要再设置渲染状态和一大堆渲染数据设置,只需要物体跟缓冲区的数据绑定就可以了。
SRP Batcher 正是通过批处理一系列 Bind 和 Draw GPU 命令来减少 DrawCall 之间的 GPU 设置。
兼容SRP Batcher:
首先需要勾选 SRP Batcher:


其中Shader中所有的内置属性例如unity_ObjectToWorld,unity_SHAr等,都要在一个名为UnityPerDraw的CBUFFER中声明;
所有的Material属性都要在一个名为UnityPerMaterial的CBUFFER中声明。
如果shader报错:Shader error in‘Unlit/SampleUnlit’: redefinition of ‘unity_ObjectToWorld’,重复定义,如果自己的shader代码里面没有,那么就是引入了其他的库文件里面包含了该变量。
最后,我们看Shader的面板,如果出现了类似的提示:


则表示 该属性未包含在 CBUFFER_START(UnityPerMaterial) 里面。
注意:如果Shader使用了多Pass渲染,则会打断 SRP Batcher。
内置渲染管线和URP的CPU原理图对比:


渲染管线:(红框部分就是SRP Batcher优化的性能部分)


URP:在把材质数据和物体数据上传好后的流程图:


其中SRP Batcher并没有减少DrawCall,而是优化了DrawCall之前的设置开销。
四、升级指南

配置部分
1. 通过Unity的PackageManager安装对应的渲染管线工具包,要使用URP通用渲染管线,则需要安装Universal RP,包含ShaderGraph。


2.安装了渲染管线工具包之后,在编辑器的“项目”窗口中右键单击,然后选择Create > Rendering创建对应的渲染管线配置。


3.接着在Editor - Project Setting - Graphics中的Scriptable Render Pipeline Settings设置渲染管线配置文件。


Shader部分
参考Builtin升级URP学习笔记(一)
五、其他

渲染

渲染URP渲染场景通过:

[*]Forward Renderer.(前向渲染)
[*]Shading models for shaders shipped with URP(URP附带了着色器的阴影模型)
[*]Camera(摄影机)
[*]UniversalRP Asset(通用渲染管线资产)
在前向渲染器中,URP实现了一个渲染循环,告诉Unity如何渲染一个帧。


当渲染管线在图形设置中激活时,Unity使用URP来渲染项目中的所有摄像机,包括游戏和场景视图摄像机、反射探针和检查器中的预览窗口。
URP渲染器为每个摄像机执行一个摄像机循环,执行以下步骤:

[*]筛选场景中渲染的对象
[*]为渲染器构建数据
[*]执行一个渲染器,该渲染器将图像输出到framebuffer
URP在rendering loop的开始和结束时提供了回调函数,同样在camera loop的开始和结束也提供了回调函数。
Camera loop
步骤具体描述Setup Culling Parameters配置剔除光照和阴影的相关变量。这部分可以在custom renderer中重写Culling使用前一步中的剔除相关变量计算出摄像机可见的渲染清单,阴影和光照。剔除变量和相机层级距离(layer distances)影响剔除和渲染表现Build Rendering Data根据剔除结果,URP资源的质量设置,摄像机,和运行平台构建RenderingData。RendereringData将给renderer提供rendering work的数量和相机要求的质量和当前选择的平台Setup Renderer创建一系列渲染队列,根据渲染信息对他们进行排序。此部分可在custom renderer中重写Execute Renderer执行渲染队列中的每个渲染通道。将结果输出到framebuffer中光照

使用通用渲染管线(URP),可以实现真实的照明,这是适合一系列的艺术风格。
所有Unity的渲染管线共享共同的照明功能,但是每个渲染管线都有一些重要的区别。
通用渲染管线(URP)不同于Unity的普通照明功能的地方是:

[*]光照组件检查器,它显示一些URP特定的控件。
[*]通用附加照明数据组件,它允许Unity存储URP的特定的光的相关数据。
[*]URP不支持使用Enlighten的实时全局照明。Enlighten 已经被弃用了。


关于Unity中照明的一般介绍和常见照明工作流程的例子,请参阅Unity手册中的照明部分。
摄像机

Unity中的摄像机的工作方式类似于现实世界中的摄像机:它捕获3维空间中对象的视图,并将其展平以将其显示在2维表面上。
URP中的摄像机基于Unity的标准摄像机功能,但有一些显着差异。
差异:

[*] Universal Additional Camera Data组件,该组件扩展了摄像机组件的功能并允许URP存储与摄像机相关的其他数据。
[*] Render Type设置,它定义了URP中的两种摄像机类型:Base和Overlay。
[*] Camera Stack System,可让您将多个摄像机的输出分层为单个组合输出。
[*] Volume System,可让您根据场景中给定的变换位置将后处理效果应用于摄像机。
[*] Camera组件,在Inspector面板中公开特定于URP的属性。
有关Cameras在Unity中的工作原理的一般介绍,以及常见Camera工作流程的示例,请参阅Cameras上的Unity手册部分。
后处理

URP包含自己的后处理,这不需要下载其他的包。
实现使用的Volume system与HDRP相同。我们可以添加Volume Override以相同的方式。下面展示后处理的效果:
无后处理:


有后处理:


如何在URP中配置后处理
在URP模板场景中使用后处理,后处理在 URP 模板中的示例场景中预配置。
要查看预配置效果,请选择场景中的Post-process Volume。


在新的场景中配置后处理
1. 选择相机,然后选择Post Processing复选框。


2.在场景中添加带有Volume组件的游戏对象。此指令增加了Global Volume。选择GameObject > Volume > Global Volume。
3.选择Global Volume游戏对象。在Volume组件中,通过单击配置文件属性右侧的新按钮创建新配置文件。


4. 通过将Volume Overrides添加到Volume组件,将后处理添加到摄像机中。


移动设备上的URP后处理
后处理将占用很多帧时间。下面这些效果在移动端也是比较友好的。

[*]Bloom
[*]Chromatic Aberration
[*]Color Grabing
[*]Lens Distortion
[*]Vignette
页: [1]
查看完整版本: 【Unity Shader】Builtin升级URP学习笔记(二)