[Unity] 【转载】Unity轻量级渲染管线LWRP源码及案例解析

查看:2572 |回复:0 | 2019-11-27 09:15:23

您需要 登录 才可以下载或查看,没有账号?注册

x
本帖最后由 kanisen 于 2019-11-26 15:42 编辑

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





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

4bd787ee-fc85-4547-bc8b-0d77045416fd____01.jpg


演讲内容

大家好,我的演讲题目是《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下载,也可以自己进行修改。



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

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

LWRP与内置渲染管线对比

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

很多人可能还没有去了解轻量级渲染管线LWRP,就觉得是不是赶不上目前的主流画面。所以,我先给大家对比一下轻量级渲染管线LWRP和老的渲染管线有什么差别。



如上图所示,最重要一点就是第一行,老的渲染管线使用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,修改光照模型就可以了。



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

上图显示的是新增功能Custom Render Pass,主要是为了提供可扩展性。我们还是希望大家不改源码就可以进行扩展,所以提供了这种方式。如果这样还不够的话,大家再去考虑改源码。

我们推荐大家,可以不改源码实现,就尽量不改源码,因为改了源码后,升级会很麻烦,自己要升级修改过的代码到新的版本,要避免冲突,增加大家的工作量。



如上图所示,在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中。



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



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



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

如果你要用一个CommandBuffer的话,不要自己New一个,而是在Pool里拿一个,因为它会缓存下来,等下一帧需要用的时候,可以在库里拿出来直接用,而不是每次New一个,Delete一个,这样性能会比较差。



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



Core RP其实很简单,我主要希望让大家知道,没有必要花太多的时间看这些东西,因为它里面没有太多的内容。

LWRP源码解析-Lightweight PR

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



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



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



第一步要在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的一些参数。



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

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



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

如果大家以后自定义轻量级渲染管线LWRP,希望增加自己的参数,找到LightweightRenderPipelineAsset这个类,并添加参数就可以了。



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进行配置和渲染执行。





演示项目:Custom Renderer


我们再看一个Unity 2019.1发布时新推出的Demo。


Custom Renderer下载地址:https://github.com/Unity-Technologies/LWRP-CustomRendererExamples




这个Demo是要实现什么效果呢?


过去我们制作射击类游戏,经常要做的一件事情是这把枪用不同的FOV单独渲染。如果枪不进行特殊处理,使用和场景相同的FOV去画的话,画出来会很窄,占屏幕面积很小,很不美观。所以过去制作FPS的游戏经常要单独画枪,它的FOV可能会小一点,这样它占的屏幕空间会更大。


过去没有可编程渲染管线SRP,过去在内置渲染管线Pipeline里,我们要用二个相机,一个相机画枪,一个相机画场景,这样可以设置不同的FOV即视角。但是这样的问题是过去Unity的Camera其实很费性能,即使加入一个什么Camera都不做,仍有很大的消耗。


因为它会计算相机的剔除,Flatten裁剪之类的计算,所以相机越多性能会越差。我们建议大家尽量不使用多个Camera,能用一个Camera解决就用一个Camera。现在有了可编程渲染管线SRP,我们就可以用一个Camera来解决。




如上图所示,这里面创建了一个Renderer,这个Renderer也是在刚刚创建Lightweight Render Pipeline里创建的Forward Renderer,这里所谓的Custom Renderer就是创建一个Forward Renderer,但是我们可以对它做一些定制。


创建这个Asset,这个Demo的Asset已经创建好了。我们看一下这个Demo,它的Renderer里有三个Renderer Feature,它们的用途是什么呢?


默认的场景渲染是放置在最上面,是不可调整的,除了First Person Object的Layer没画,其它的场景对象都是在这里上面渲染的。


下面有三个Feature是用于渲染枪的。第一个Render Feature画枪上不透明的部分,后面二个Render Feature画半透明的部分。因为枪上有一些液体,液体是半透明的,其它地方是不透明的。


相机上设置了比较大的FOV,然后在第一个Render Feature这里是设置相机的FOV是40,然后主场景相机的FOV是80。常见的FPS游戏使用的FOV是80。所以在Render Feature里某些对象可以有自己的FOV。


我们还可以给它设置不同的材质参数,模板缓冲区,Stencil Buffer等。这里我们用到了Stencil Buffer,还有Position偏移等参数,这些是让我们管理场景中不同物体渲染的参数,在过去的话,有些参数只能在相机上设置。


简单介绍一下模板缓冲区。在做这种效果的时候,我们目标是先画枪,因为枪总是在场景的前面。过去画半透明物体时,我们先画离相机最近的,再画远的,这样深度裁剪时,前面物体会挡住后面的物体,不会重复填充像素,这样性能会更好一些。


怎么做到这种功能呢?首先这个Render Feature是设置了Event,它的渲染顺序是Before Rendering Opaques,这样在不透明物体之前先画枪,然后把Stencil Buffer写成1。


等画完枪再去画场景的时候,它会检查Stencil Buffer是0才会去填充。因为枪填充过的像素Stencil已经是1了,在画场景的时候就不会重复填充枪的像素,省掉一些像素填充。这就是对Stencil Buffer的利用方法。




下面介绍一下Renderer和Render Feature。我们会看一些源码,讲解怎样去理解Renderer?




如上图所示,有一个抽象类ScriptableRenderer,里面定义了Render Pass的数组,还有Render Feature的数组。


在执行的时候按照几个Block执行Renderer Feature,也就是说Renderer里面存储了很多的Render Pass。其实Render Feature也就是多个Render Pass的集合。


可编程渲染管线里面有很多Render Pass,我们可以添加自己的Render Pass,也可以删除一些Pass,可编程渲染管线就是按顺序执行不同的Render Pass。


下面有个类叫EnqueuePass,如果要自己写Render Feature的话,要把自己的Render Pass加入到这个队列里面,加入上面的List数组里面。




如上图所示,我们看到它执行时会执行一个个Block,Block里有一个while循环,去执行每个Pass。


下面是执行Pass的函数。最下面这个SortStable函数不太醒目,但它很有用的,它用来排序所有Render Pass的执行顺序。


SortStable函数控制加入Pass后,Pass是在什么时间点画的,Pass的执行顺序是什么样的。它会For循环所有的Pass,然后做排序,排序时会对每个Pass做比较。


每个Pass重载Operator的类,重载Operator类会根据Event的值,决定在不透明之前画还是半透明之前画,还是在天空盒之前画,它会根据Event在SortStable函数中进行排序。




如上图所示,我们看看Forward Renderer这个类,它继承自ScriptableRenderer,主要是用来添加Forward Rendering里的各种Pass。


其实刚刚ScriptableRenderer是空的,里面没有Pass,它最终渲染的Pass是使用这里的Forward Renderer,它派生了刚才的类后负责往里面加入Pass,加了正向渲染的Pass,先画不透明再画半透明,再画后处理之类。


演示项目:BoatAttack


我们再看一个Unity 2019.1之前发布的官方Demo-BoatAttack。BoatAttack中水的效果就用到了Render Feature,它实现了焦散的效果,代码非常简单。


BoatAttack下载地址:https://github.com/Verasl/BoatAttack




代码中有二个类Render Feature和WaterCausticPass。Render Feature继承自ScriptableRenderFeature。写了Render Feature之后,引擎就会在下拉菜单里增加这个Render  Feature的选项,这个Render Feature负责把下面这个Render Pass加到Renderer里面。Render Feature可以在渲染管线的某个时间点增加一个Pass或者多个Pass。


下面是Render Pass,焦散的Render Pass其实比较简单,就是画了一个全屏的Quad,去根据深度算出世界的坐标,计算阳光投影过去,相当于把焦散的图投到水底的地方,使用全屏的Quad来实现的。




如上图所示,红框标出了关键的几个地方,AddRenderPasses会往Renderer里加入Pass,下面的Pass是某个效果的实现。


我们再看一下ScriptableRenderPass这个类。




WaterCausticsPass这个类继承自ScriptableRenderPass,这个类重要的是要有RenderPassEvent,它里面有Pass执行的时间点,用来控制每个pass的执行顺序。在ScriptableRenderPass里,可以在构造函数里面去指定了Event在什么时间点执行,默认的话Event是在不透明物体之后画,即AfterRenderingOpaque。


在很多RenderPass的Pass代码里,我们都无法直接看到Event,它其实是在基类ScriptableRenderPass里设置了默认Opaque,所以如果你没有看到它设置在什么时间点执行的话,它默认在不透明物体之后画。


最下面的红框部分Operator用来比较二个RenderPass应该先画谁,根据Event的数值,转换成Int来比较。


LWRP定制


如何基于Unity轻量级渲染管线LWRP进行一些简单定制?应该怎么做?




不久前一位客户提出一个疑问:目前只能在Asset里添加Render Feature,一般是创建Renderer Asset,在Inspector里添加Render Feature,Asset里有二个Render Feature,那么如何在运行时再添加一个Render Feature?




经过调查,我发现目前设计的确没有考虑到这种情况。如果不改代码的话,目前无法实现这个需求。于是我尝试通过修改一点代码,实现在运行时可以增加一个Render Feature。


我调查的过程是:首先要找一个场景进行测试,于是我找到了BoatAttack项目用于做测试。刚好它的Renderer里有二个Render Feature,所以我首先把它默认Asset里的Render Feature删掉,试试是否可以在运行时增加Feature。




我的目标是:在运行时,添加了UI的Button,点Button时会添加该Render Feature到Renderer上。




我查看了源码,发现在Forward Renderer类的Setup里有这个操作,是把所有Render Pass加到Renderer里面。


但是我发现它加到了Forward Renderer的基类里的一个数组里,这个数组不是一个Public的变量,从外面不能直接访问,m_RenderFeatures这个变量不能公开访问,而且也没有修改这个数组的API,导致不能增加,删除Render Feature。




那么我如何修改该数组呢?为了节省时间,我暴力的把它改成了Public,然后就可以在脚本里访问这个变量,给它增加Render Feature了。这是为了给大家说明我们可以定制LWRP,但这种做法其实不太好。




将它暴露成Public之后呢,我就另写了一个脚本,加到相机上面。在相机上面进行判断,如果相机上设置了Renderer,我就获取相机上的Renderer,如果相机上没有设置Renderer,我就从Asset上获取Renderer。


获取Renderer后,向Renderer里添加Render Feature。刚好Render Feature也是一个Asset,我在上面声明了Renderer Feature的变量,可以直接把Renderer Feature Asset拖过来,在运行时把这个Asset添加到这个Renderer上面。




下面是定制的效果视频。


我会在这点这个按钮,可能效果不太明显。在我点按钮之前,水下没有焦散效果,点了按钮后,就可以看到Caustic焦散效果。


定制案例 :Rendering Frequency for APP


还有一个非常小的定制案例,过去Unity一般用来做游戏,做VR、AR,几乎没有人用Unity做手机上普通的App。但Unity中国的团队开发了一套工具叫UIWidgets,可以用它来做App。


过去最主要的问题是UI不方便。App开发者用我们的UGUI时,由于它是用来做游戏的,他们会觉得要重新学习,而且用起来也没有做App的那些工具方便,因此我们就制作了UIWidgets。UIWidgets的问题是:如果里面有3D场景的话,每帧都要渲染。


作为App来说,功耗上和消耗电量会比较大一些,因为普通App和游戏不同,不会不停地刷新画面。所以我们有这个需求:能不能不要每帧都渲染。




刚好我们有脚本的ScriptableRenderPipeline,我们可以在不需要渲染的时候关闭渲染,因为App不是每帧都需要操作,可能我们在看一段话时,至少会几分钟都没有操作,也没必要重新渲染。


代码实践很简单,首先在LightweightRenderPipeline的主要Render函数里进行判断,判断它过了多少毫秒,如果超过特定毫秒,会继续执行,如果没到特定毫秒,就先Return。


当然,此时引擎的主线即逻辑帧还会执行。你可以设置它的Frame rate为30帧或60帧,但渲染会直接跳过,不做渲染操作,从而节省一些GPU的功耗。


这是一个很简单的定制案例。大家考虑如果用Unity开发手机App的时候,因为游戏引擎会每秒几十帧渲染整个场景,导致手机功耗很高。那有没有可能没有输入操作的时候停止渲染呢?


因为现在有了可编程渲染管线SRP,会非常简单。实现的方式就是在Lightweight RenderPipeline的主函数里判断要不要渲染,如果没有输入操作,就跳过渲染的执行。


注意事项


下面介绍我使用轻量级渲染管线LWRP遇到的几个坑。


如果希望要定制轻量级渲染管线,你要修改它的源码,应该怎么做呢?




我们推荐的方法是先到Github上把SRP可编程渲染管线源码的工程Clone下来。


下载SRP可编程渲染管线源码:https://github.com/Unity-Technologies/ScriptableRenderPipeline.git


然后,在Packages文件夹下找到manifest.json文件,它可以配置是使用在Package Manager里下载安装的Package还是自己修改的Package。


在这里可以指定路径,指向我们Clone下来的地址,然后现在开始,游戏里就使用我们Clone下来的目录下的轻量级渲染管线代码,直接在代码里修改就好了,改完后可以提交到自己托管源代码的服务器上。




还有一个关于Shader的小坑。大家都知道,写Shader时会在最上面定义Shader属性,过去在Shader Property上,我们会随便写一个变量,half+变量,这样写上去就行了。


到了轻量级渲染管线LWRP中,你必须把它加入到Constant Buffer里面,否则变量无效。定义后,即使在外面材质部分调参数也会没有作用。所以一定要记住这点。


Shader有一个需要特别注意的地方,在添加Shader Properties的时候,一定要把变量添加到Constant Buffer里面,否则添加的属性无效。


另外,如果在工程里需要引用轻量级渲染管线里的某个Shader,它的引用路径要像上图最下面这部分,大家写的时候要按这样的格式去写URL。


另外如果想在Assets路径下的Shader内Include Package里面的Shader,按照这个路径去Include。


下面是一些现有的LWRP相关的示例工程。


轻量级渲染管线LWRP


https://github.com/Unity-Technologies/LWRP-CustomRendererExamples


https://github.com/Verasl/BoatAttack


Outdated Sample


https://github.com/johnsietsma/ExtendingLWRP


https://github.com/UnityTechnologies/LWRPScriptableRenderPass_ExampleLibrary


https://github.com/phi-lira/SIGGRAPH2018-StudioWorkshop


https://github.com/stramit/SRPBlog/tree/master/SRP-Demo


https://github.com/pbbastian/SRPFromScratch


https://github.com/UnityTechnologies/AngryBots2


需要注意:由于Unity 2019.1推出之后有很大的更新,导致大部分老的Sample工程在2019.1上打开会报错,只有前面二个工程不会报错。


不过大家还是可以用它们来了解LWRP开发的整个历程,了解LWRP是如何一步步发展过来的。


这是我今天分享的全部内容,谢谢大家 !

评分

参与人数 1元素币 +12 活跃度 +13 展开 理由
源支始 + 12 + 13

查看全部评分

2019-11-27 09:15:23  
 赞 赞 0

使用道具 登录

0个回答,把该问题分享到群,邀请大神一起回答。

CG 游戏行业专业问题

手机游戏引擎手游引擎Unity3D技术
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表