Unity轻量级渲染管线LWRP源码及案例解析(上)

Unity轻量级渲染管线LWRP源码及案例解析(上)

原创: 张黎明 Unity官方平台 今天git

收录:白袍扶心 (之前、当前、将来笔记都在GIT了-嘿嘿)github

GIT: https://github.com/daozhangXDZ/DaoZhang_ProgramNote/tree/master/Unity/ScriptRenderPipelineweb

小道说一个LWRP(这里和原来Shader的写法有区别,不过这样更对应GLSL和HLSL,OPENGL和DX你懂的):
CBUFFER_START(UnityPerMaterial)
float _Outline;
float4 _OutlineColor;
CBUFFER_END算法

原创: 张黎明 [Unity官方平台]编程

今天本文将分享Unity大中华区技术总监张黎明在Unite 2019上的技术演讲-Unity轻量级渲染管线LWRP源码及案例解析。缓存

受篇幅限制,本次演讲将分享二篇内容。本文将介绍可编程渲染管线SRP和轻量级渲染管线LWRP、LWRP与Built-in内置渲染管线区别、LWRP源码解析Core RP和Lightweight RP。编辑器


演讲内容函数

你们好,个人演讲题目是《Unity轻量级渲染管线LWRP源码及案例解析》。性能

你们可能发现技术分享一般去讲使用为主,讲源码的很是少,为何我会选择讲源码?学习

这是出于有二个缘由:

  • 第一个缘由是轻量级渲染管线LWRP实在是太新了,根本就找不到太多文档。我原本想找文档给你们讲解一下,结果发现没有。我本身学习也只能经过查看源码的方式,咱们内部也没有文档。

  • 第二个缘由是咱们发现一些客户已经开始使用了,并且他们每一个游戏都有一些特殊的需求,有的游戏可能须要对Unity轻量级渲染管线LWRP进行一些定制。这样就必需要查看源码,从而在游戏中达到更好的效果。

下面是我本次分享的主要内容,首先会简单介绍什么是Unity的可编程渲染管线SRP以及轻量级渲染管线LWRP。


可编程渲染管线SRP

首先,简单介绍一下Unity的可编程渲染管线SRP。


过去,咱们有一套内置渲染管线的Render Pipeline,渲染管线所有写在引擎的源码里,使用C#代码编写。你们基本上不能改动,除非是买了Unity的源码客户,固然大部分开发者是不会去改源码,因此过去的管线对开发者来讲,很难进行定制。

对于咱们来讲也有负担,由于咱们要在一个渲染管线里面支持全部的二十多个平台,包括很是高端的PC平台,主机平台,也包括很是低端的平台,很老的手机也要支持。

因而,这套代码会变得愈来愈臃肿,很难作到使效率和效果作到最佳,因此咱们如今有一套新的基于脚本的渲染管线。

它主要把渲染管线拆分红二层:

  • 一层是比较底层的渲染API那层,像OpenGL,D3D等相关的都封装起来。
  • 另外一层是渲染管线比较上层的描述,上层代码使用C#来编写。在C#这层不须要关注底层在不一样平台上渲染API的差异,也不须要关注具体如何作一个Draw Call。

咱们在C#这边会一批对象一批对象的画,这样性能也会更好一些。

Unity官方基于Scriptable Render Pipeline可编程渲染管线提供了二套模板:一个是轻量级渲染管线LWRP,一个是高清晰渲染管线HDRP。

高清渲染管线HDRP是所有基于Compute Shader,基于最新的硬件来开发的,能够达到顶尖的渲染效果。例如Unity的官方演示项目《异教徒》,它的效果很是惊艳。

轻量级渲染管线LWRP

另一个渲染管线是轻量级渲染管线LWRP,主要是为了移动平台设计,也就是最流行的手机游戏平台,它能够达到更高的效率,而后可定制性也更好。

这二个模板都是开源的,你们均可以在Github下载,也能够本身进行修改。

img

高清晰渲染管线HDRP只支持最高端的平台,即目前比较好的PC和主机平台,但轻量级渲染管线LWRP支持全部的平台。

咱们的目标是轻量级渲染管线LWRP在性能方面比过去内置的管线更好。在Unity 2019.1中,轻量级渲染管线LWRP已经成为正式版本,可用于正式的项目制做。

LWRP与内置渲染管线对比

咱们和不少客户有过沟通,发现其实你们对轻量级渲染管线LWRP不是很理解。不少人一听到轻量级管线LWRP就以为有点LOW,以为如今你们制做移动游戏都开始作AAA级,画面都要PBR,都要超大世界,各类特效,后处理都加上。

不少人可能尚未去了解轻量级渲染管线LWRP,就以为是否是赶不上目前的主流画面。因此,我先给你们对比一下轻量级渲染管线LWRP和老的渲染管线有什么差异。

img

如上图所示,最重要一点就是第一行,老的渲染管线使用Multi-Pass的Forward Rendering,就是多Pass的正向渲染。最大的问题是若是要在场景里要加不少动态光的话,每个动态光都有可能会增长一个Pass,这个动态光所影响的物体要多画一遍。

这就致使若是游戏里想要有多个动态光的话,可能这个场景会被画不少遍,性能会不好。它带来的问题是全部的游戏几乎都不会用多个动态光,由于实在太费性能了。

在过去制做移动的游戏的过程当中,你们的标准作法都是烘焙Lightmap。若是能够用多个动态光,咱们其实能够作出更酷的效果。

例如,制做一个有魔法的游戏,游戏中每一个人都释放一个魔法球出来,咱们彻底能够给它加一个动态的灯光,跟着它一块儿飞出去,这样的效果很是酷。可是由于过去每增长一个动态光都会致使渲染Pass增多,因此你们就不敢使用。

如今轻量级渲染管线LWRP就解决了这个问题。咱们实现了一个单PASS的正向渲染。咱们能够支持多盏动态光,可是所有动态灯光都会放在一个Pass里渲染,这样带来的问题是咱们要限制灯光的数量,由于每次Draw Call去画的时候,传给GPU的参数是有限的。

若是灯光数量特别多,参数太多,那就会没法在一次Draw Call里完成不少个灯光。因此咱们有一些限制,在轻量级渲染管线LWRP里,目前是支持1盏平行光,每一个对象可能只能接受4个动态光。每一个摄像机也有一些限制,这是为了咱们能够把全部的计算放在一个Pass里面。

Unity2019.2,Unity 2019.3可能会把这个限制再提升一些。相信大部分的游戏也不太会在一个场景里加太多动态光,若是能够作到8盏动态光,可能对于大部分游戏来讲也足够了,这样在一个Pass里的渲染性能会更好。

另外,轻量级渲染管线LWRP还有新加入的功能,包括Scriptable Render Pass,还有SRP的Batcher合批。合批会比过去好一些,轻量级渲染管线LWRP仍会支持静态合批和动态合批。咱们还会提供可经过脚本定制的Render Pass以及Custom Renderers。

不少客户给咱们反馈,如今使用轻量级渲染管线LWRP,最欠缺的是二个功能:

  • 首先是目前还未支持的Shadow Mask,这在老的内置渲染管线里已经有了。咱们计划在Unity 2019.3提供Shadow Mask的功能。
  • 其次是延迟渲染Deferred Rendering,它在老的管线有,新渲染管线没有,它也会在Unity 2019.3提供。

关于PBR,你能够认为它彻底不比内置渲染管线差,它也是使用了移动平台上的最好光照模型。若是再往上提高的话,就是HD渲染管线的PBR光照算法,这样的话就太费性能了,可能不适合你们作移动游戏了。

在PBR这方面,它基本和内置渲染管线是保持一致的。若是你们仍是不满意的话,能够修改轻量级渲染管线的Shader,修改光照模型就能够了。

img

如上图所示,这是咱们本身进行了一些测试结果,基本上在各个方面的性能都是比内置渲染管线要好。

img

上图显示的是新增功能Custom Render Pass,主要是为了提供可扩展性。咱们仍是但愿你们不改源码就能够进行扩展,因此提供了这种方式。若是这样还不够的话,你们再去考虑改源码。

咱们推荐你们,能够不改源码实现,就尽可能不改源码,由于改了源码后,升级会很麻烦,本身要升级修改过的代码到新的版本,要避免冲突,增长你们的工做量。

img

如上图所示,在Unity开发路线图里,除了如今提供的Forward Renderer,Unity 2019.2会提供一个2D的Renderer,它主要提供2D的光照和2D的阴影效果。Unity 2019.3会增长Deferred Renderer,一个延迟渲染的Renderer。

LWRP源码解析-Core PR

若是要使用轻量级渲染管线LWRP,你须要在Package Manager里导入二个Package:Core RP和Lightweight RP。

Core RP是高清晰渲染管线HDRP和轻量级渲染管线LWRP共同依赖的包,由于有一些代码须要共用,因此咱们把这部分代码拆到Core RP中。

img

以下图所示,咱们看一看Core RP文件夹的结构。

img

Editor文件夹中是编辑器脚本,作一些Inspector里显示参数的代码。Runtime文件夹中是主要代码,有一些共用的Shader Library,共用的Shader代码放在这里,其它还有一些测试代码。

img

在Runtime > Common文件夹中有一个CommandBufferPool,轻量级渲染管线LWRP和高清晰渲染管线HDRP都要用到它。

若是你要用一个CommandBuffer的话,不要本身New一个,而是在Pool里拿一个,由于它会缓存下来,等下一帧须要用的时候,能够在库里拿出来直接用,而不是每次New一个,Delete一个,这样性能会比较差。

img

Volume文件夹是实际上相似于Post-Processing Stack后处理栈里面的PostProcessVolume,这是一个通用的Volume,能够调一些渲染管线的参数,它能够在进入一个体积后调一些参数。

img

Core RP其实很简单,我主要但愿让你们知道,没有必要花太多的时间看这些东西,由于它里面没有太多的内容。

LWRP源码解析-Lightweight PR

咱们的重点是另外一个Package,即Lightweight RP里面有哪些东西。

img

本次重点会讲下图中这些类,这是源码中的一些类,我要介绍这些类的用途是什么?

img

咱们先作一点轻松的事情,我制做了一个很简单的Demo,简单说一下轻量级渲染管线LWRP怎么使用?

img

第一步要在Package Manager里面导入package,导入以后须要Create一个Light Weight Render Pipeline Asset。建立后咱们有Graphics Settings。

咱们要把Asset拖到Scriptable Render Pipeline Settings这个位置,而后引擎会把当前渲染管线改为刚刚建立的Asset这种类型的渲染管线,老的内置渲染管线就开始不执行了。建立的轻量级渲染管线LWRP在Asset上有一些参数设置。

首先有Renderer,而后有二个选项Depth Texture和Opaque Texture。Render Pipeline Asset上会保存轻量级渲染管线LWRP的一些参数。

img

这里有一个刚刚提到的Opaque Texture选项,它对应的代码就是LightweightRenderPipelineAsset类。

咱们写了这个类以后,就能够在Editor里右键新建一个这种类型的Asset,它继承自RenderPipelineAsset这个类。

img

LightweightRenderPipelineAsset类中声明了一些变量,这些变量就是在Inspector看到的Render Pipeline Asset上的参数,它们都是在这个类里面定义。也就是说,这个类是用于序列化Lightweight Pipeline上全部的参数。

若是你们之后自定义轻量级渲染管线LWRP,但愿增长本身的参数,找到LightweightRenderPipelineAsset这个类,并添加参数就能够了。

img

RenderPipelineAsset继承自ScriptableObject,你们应该知道,ScriptableObject这个类是专门用于序列化数据的,因此它在这里序列化轻量级渲染管线LWRP的数据。

而后看一看Opaque Texture选项,这是轻量级渲染管线LWRP提供的一个功能。

在内置渲染管线Pipeline中,若是想作一个折射的效果,例如水的效果,过去的作法是用GrabPass,在Shader里写一个GrabPass,它会抓取当前的屏幕画面,而后对画面作扭曲和水的扰动等效果。

GrabPass的问题是它的性能不太好,并且在不一样手机硬件上,不一样渲染API上的实现方式不同,有的硬件上性能特别差,致使帧率降得特别厉害。

如今咱们在轻量级渲染管线LWRP中,能够直接在不透明物体画完后,勾上Opaque Texture选项后,它就会把当前画面抓取到RenderTexture里。若是要作折射效果或是水的效果,或者是玻璃的折射的话,直接用该选项便可。


再看一下这个Demo,勾选Opaque Texture后,它用起来很是简单。在Shader中,咱们须要去定义一个CameraOpaqueTexture的变量,定义了后就能够直接在后面的Fragment Pixel Shader去采样。

咱们直接能够采样贴图的Sampler,能够作一些扰动效果,很是方便。咱们没必要像过去那样使用GrabPass,致使一些性能问题。


最主要的渲染管线的执行是在LightweightRenderPipeline类中,它继承自RenderPipeline基类。这个基类实际上是一个Interface,里面其实没有作什么实现,全部实现都在这个轻量级渲染管线脚本里。

如上图所示,这个主的渲染函数也很简单,就是For循环全部相机,而后调用RenderSingleCamera,渲染每一个相机的函数,逻辑比较简单。


如上图所示,在RenderSingleCamera中有几行比较重要的代码。上面这行会进行判断,如今在SRP里能够有一个额外的数据。在Lightweight Render Pipeline和HD Render Pipeline上的参数都不同,HD的参数会多不少。它会把这些不同的参数拆出来并进行判断。

这里有一个if判断,用来判断相机上的参数有没有设置Renderer。若是有,就优先用相机上的Renderer。若是没有设置,就用Render Pipeline Asset上设置的Renderer。

在LightweightRenderPipelineAsset上能够选择Renderer,上面有Custom和Forward Renderer二个选项,它本质上也是Forward Renderer。

在相机上也能够选择Renderer Type,能够选择使用刚刚Asset中的设置,也能够选择在每一个相机用不一样的Renderer。代码里会优先使用相机上的设置,若是相机没有设置,它会使用Asset设置的Renderer。

最下面的代码会调用Renderer.Setup进行配置和渲染执行。

小结

在本篇中,张黎明介绍可编程渲染管线SRP,LWRP与内置渲染管线区别,LWRP源码解析Core RP和Lightweight RP。在下一篇中,他将分享如何定制轻量级渲染管线LWRP。

更多Unite大会精彩演讲内容分享,尽在Unity Connect平台(Connect.unity.com)。

下载Unity Connect APP,请点击此处。 观看部分Unity官方视频,请关注B站账户:Unity官方

相关文章
相关标签/搜索