URP管线修改落地实战

URP管线修改落地实战

URP作为最近越来越多的新项目开始使用的管线,到很多老项目开始进行升级,很多人会遇到各种问题,比如为什么升级到了URP,性能并没有变得更好,甚至在低端机上还下降了?GrabTexture机制没有了,怎么做扭曲效果?想用线性空间但UI颜色不对怎么办?URP为什么值得升级?等等。

文章会从项目制作的角度,从基础功能修改入手,到项目层面一些刚需修改,来教会大家如何修改URP管线,从而达到自己想要的目的和效果。文章适合能看懂代码的技术美术,源码之下,了无秘密!

说明:本课程主要对URP管线在项目中的实际应用落地进行讲解和实现(附带代码可有效运行在Unity 2021.3.4f1版本上,URP版本为12.1.7,但每个项目需要自行理解整合使用)。

作者苏晟晖是资深客户端程序,项目渲染负责人。2006年毕业,曾工作于SEGA,KONAMI,制作过实况足球,也做过端游MOBA,参与过MLBB和MLA。


目录

1|前言
2|身边实用的工具
3|核心代码的简单理解
4|实战-修改Camera的附加数据(示例中有具体实现代码)
5|实战-线性空间与伽马空间共存(示例中有具体实现代码)
6|实战-以Volume的方式添加后处理(示例中有具体实现代码)
7|不额外增加Camera实现扭曲效果(代码中不附带)
8|分辨率分离的做法和优劣(FSR)(代码中不附带)


本篇转载自《URP管线修改落地实战》的第1-3节。

1|前言

本课程主要对URP管线在项目中的实际应用落地进行讲解和实现(附带代码可有效运行在Unity 2021.3.4f1版本上,URP版本为12.1.7,但每个项目需要自行理解整合使用)。

URP作为最近越来越多的新项目开始使用的管线,到很多老项目开始进行升级,让很多人遇到了各种问题,比如为什么升级到了URP,性能并没有变的更好,甚至在低端机上还下降了?GrabTexture没有了,怎么做扭曲效果?想用线性空间但UI颜色不对怎么办?URP为什么值得升级?等等。

就以上问题,也许你可以从下面的内容获得答案:

  1. 实用的工具
  2. 核心代码的简单理解
  3. 扩充UniversalAdditionalCameraData
  4. 线性空间和伽马空间共存(UI的Atlas,文字等)
  5. 以Volume的方式添加后处理
  6. 不额外增加Camera实现扭曲效果(Grab)
  7. 分辨率分离的做法和优劣(FSR)

未来有新的值得记录的内容也会继续更新。


2|身边实用的工具

工欲善其事,必先利其器。我们想要用好URP,或者说改好URP,下面两个工具,我们一定要掌握好。

1. Frame Debugger
Unity自从提供了Frame Debugger之后,管线调整以及问题追述都比之前方便和明确很多。

我们通过上图(左边)可以看到,场景里有2个Camera,他们分别用了什么管线配置,以及绘制的顺序和内容,并且在点选单项后,可以看到绘制的具体内容和数据(右边)。

左边的每一项,在UniversalRenderer.cs里都是一个Pass,建议学习的时候先在代码里把每个Pass对应的内容都先熟悉,这样有利于之后对管线进行修改(引用某人的一句话:源码之下无秘密,看源码这事,不能偷懒)。

由此可见,我们可以通过Frame Debugger来确认我们修改代码后期望的渲染顺序,渲染内容,渲染结果是否正确,所以,在我们修改了管线的代码后,一定要在这里确认无误。

2. XCode
从项目组角度来说,我们使用XCode来进行调试通常是在项目中后期,对于很多半路被砍掉的项目来说,也许根本没有机会使用XCode就已经被砍了,但这里我想建议一下,有条件的团队可以早一些使用XCode来编译项目,iOS的环境更有利于确认管线的性能和正确性。

我们用XCode在手机上运行游戏时,在Options页面,将GPU Frame Capture设置为Metal,同时勾选下方Profile GPU Trace after capture。

然后在运行时,将左边的按钮切换到小瓶子按钮上,就可以看到App的相关性能数据。

我们点击下方M这个按键时,就会截取当前Frame的所有信息,我们可以通过截帧的信息,看到我们管线的渲染流程,以及每个Pass的消耗。

通过这些内容,我们可以很方便地知道哪些Pass的消耗太大,需要优化,哪些管线做法设计的不合理,需要优化。

更多具体内容可自行使用XCode研究。


3|核心代码的简单理解

源码之下无秘密,一定一定一定(重要的事说三遍)要花时间看一遍源码,如果全部源码看不了,起码看一下各个Pass和总管文件UniversalRenderer的实现。

这里对核心的代码做一下简单的介绍,方便之后的内容理解:

1. 管线代码文件:UniversalRenderPipeline.cs

protected override void Render(ScriptableRenderContext renderContext, List<Camera> cameras)

这个函数里面,会执行每个Camera的UniversalRenderer内的Pass,如此一来,我们就可以在每个Camera进行绘制之前,先进行一个小判断,从而来改变Camera内部绘制的流程。

2. 核心向渲染代码:UniversalRenderer.cs
这个代码里定义了所有管线流程中会使用的Pass。

我们需要创建额外的RT,也可以在CreateCameraRenderTarget函数里创建,类似下图:

3. 管线更换!=性能升级
有遇到不少朋友把Built-in管线升级到URP,然后发现低配性能降低了,其实使用URP不意味着升级了就算完成了,我们还需要对管线进行定制优化。

这里为了之后的内容便于理解,先简单解释一些点。

一些需要理解的点:
a. 由于我们在Editor下,除了GameView以外,还有SceneView,其中GameView走的是正常的Camera渲染流程(也就是说,实际有几个Camera,就会有什么样对应的管线处理),而SceneView用的是独立Camera,所以我们在修改管线的时候,需要思考同步处理SceneView内的渲染效果,代码里可以用cameraData.isSceneViewCamera的值来做判断,区分代码生效的渲染窗口,也可以避免修改管线带来编辑窗口和运行窗口效果的不统一(但在同时支持伽马空间和线性空间之后,SceneView的确有个取舍的效果不一致的问题)。

b. 我们修改管线,需要考虑到Editor没有Play的情况,以及Play的情况,因为还有半路创建Camera的情况(比如UI的Camera是用逻辑创建的,而非带在启动Scene内),这些都会影响到团队内其他人在打开项目的情况下看到的画面。

c. 一旦开始修改管线,建议从整体上进行思考,尽量不要只考虑单一功能在管线中的实现,而忽略了管线本身的承上启下的功能。


以上就是《URP管线修改落地实战》的第1-3节,此篇文章比较适合从事Unity开发的技术美术人员;希望提升修改URP管线能力,系统理解URP管线落地方法的以及对Unity的URP渲染感兴趣的同学的读者。

读完全篇后你会对URP管线有更深的理解,并了解管线修改落地的方法,课程还提供了配套工程和大部分课程内的实现代码,有助于我们自行研究。