URP系列教程 | 手把手教你如何用Renderer Feature
今天我们先讲URP的Renderer Feature,Renderer Feature可让我们向URP Renderer添加额外的渲染通道,支持我们进行Asset资产配置来重写从而可以自定义渲染的顺序、渲染的对象、材质等等。
如何新建 Renderer Feature
我们先来新建一个Renderer Feature ,首先你得有一个或者新建一个URP工程,创建Universal Render Pipeline Asset同时会生成一个Universal Render Pipeline Asset_Renderer, 创建完成后我们把Universal Render Pipeline Asset导入到Graphics Settings中。
接着我们点击生成的Renderer,然后Add Renderer Feature点Render Objects,我们就创建好一个Renderer Feature了。
我们在 Project 窗口中也可以查看,点击渲染器旁边的小三角,可以看到新建的Renderer Feature 已经是我们Renderer渲染器的子集(这里Renderer Feature我们已经重命名为Toon Outline)。
Renderer Feature 的属性简介
我们可以看到 Render Objects 的 Renderer Feature 包含一些属性;我们一个个过一下。
01 Name:首先是这个Feature的名字;
02 Event (事件):当Unity执行这个Renderer Feature 的时候,这个事件Event在通用渲染管线中的执行顺序;
03 Filters:这个设置允许我们给这个Renderer Feature 去配置要渲染哪些对象;这里面有两个参数,一个是Queue,一个是Layer Mask。
04 Shader Passes Name:如果shader中的一个pass具有 LightMode Pass 这个标记的话,那我们的Renderer Feature仅处理 LightMode Pass Tag 等于这个Shader Passes Name的Pass。
05 Overrides:使用这个Renderer Feature 进行渲染时,这部分的设置可让我们配置某些属性进行重写覆盖。
Write Depth:写入深度,此选项定义渲染对象时这个Renderer Feature是否更新深度缓冲区。
Field of View:渲染对象时,渲染器功能使用此Field of View(视场),而不是在相机上指定的值。
实战一:使用Renderer Feature来进行描边
实战是加深理论的最好途径,所以接下来要进行实战演练,我们来看下这些属性的使用情况,做一个简单的游戏场景角色的描边效果来展示下。
当然描边的方法有很多种,这里我们介绍的方法是先画模型的背面,然后使其根据法线的方向产生一定的偏移量,这些偏移量就显示为模型周围的轮廓,然后我们对其进行用户自定义的着色。
首先,我们是仅要为游戏角色Character来进行描边的操作,所以我们需要在Layer Masks上设置为Character Layer层;
然后我们创建Renderer Feature ,并将Name改为Toon Outline。
接着我们来看看Event这个属性,它是决定我们渲染哪个阶段,这里我们选择After Rendering Opaques,在渲染完不透明物体之后。
然后我们来看下Filters的两个参数一个是Queue,一个是Layer Mask。Queue:我们创建的这个Feature选择是渲染透明物体还是不透明物体,这里我们选择Opaques;Layer Mask:我们创建的这个Feature选择是渲染哪个图层中的对象;这里当然是选择我们的Character Layer。
最后我们看下Overrides中的Material参数将材质进行替换,以定义我们如何在Character Layer上渲染对象。(关于这里的材质创建我使用的是Universal Rendering Examples 中的OutlineHull,Shader使用的是ToonBasicOutline,具体的链接见文末,这里算是个伏笔,后面会带大家使用URP 已经支持的Shader Graph来进行制作 )
到这里的话,使用Renderer Feature 制作的描边效果的流程就已经结束了。为了更进一步说明Renderer Feature中的Event 属性对整个渲染的影响,我们尝试将描边的顺序改为渲染的最后一步:后处理之后进行描边处理,从而得到如下图的效果。
实战二:使用多Renderer Feature
来进行FPS游戏摄像机FOV的修改
前面我们小试牛刀,演示了使用一个简单的Renderer Feature 进行的描边操作的功能;为了更深入一步了解Renderer Feature的作用以及各个属性的意义,我们增加一点难度,这里再演示一个案例。
这个案例要实现什么效果呢?过去我们制作射击类游戏,经常要做的一件事情是这把枪用不同的FOV单独渲染。如果枪不进行特殊处理,使用和场景相同的FOV去画的话,画出来会很窄,占屏幕面积小,不美观。如下图所示;
所以过去制作FPS的游戏经常要单独画枪,它的FOV可能会小一点,这样它占的屏幕空间会更大。在内置渲染管线Pipeline里,我们要用二个相机,一个相机画枪,一个相机画场景,这样可以设置不同的FOV即视角。但是这样的问题是即使加入一个Camera什么都不做,仍有很大的消耗。现在有了URP,我们就可以用一个Camera来解决了。
这里面我使用了三个Renderer Feature去实现了这个效果。第一个Render Feature画枪上不透明的部分,后面二个Render Feature画半透明的部分比如一些玻璃冷凝管、液体。
和上一个案例我们仅作用于角色Character一样, 这里我们还是要新建一个layer,因为我们要仅针对于枪的部分去修改它的FOV(这里我们设置Renderer Feature FOV是40,然后主场景相机的FOV是80),所以这里我们创建First Person Objects Layer。如图所示我们将Terraformer_1P_Rig Layer设置为First Person Objects。
值得注意的是在我们自己新建的这个FPSSetupP1的Renderer设置里面(红色大括号所示),其中Filtering属性定义渲染器Renderer绘制哪些图层。这块渲染的是除枪以外的图层,也就是我们定义的First Person Objects Layer以外的图层,比如场景、UI、后期处理等,所以这里的Filtering设置我们要忽略First Person Objects 这个层。如下图所示:
因为我们要画不透明物体,所以这块我们需要对Stencil进行重写覆盖,这里我们打上勾表示渲染器将处理模板缓冲区值。“Value”和“Compare Function”在这里很重要,因为我们现有只想在值等于0的情况下写入像素,我们会将枪的Stencil值设为1。
说完了Renderer部分的设置,也就是渲染非枪的区域,我们来说下渲染枪的部分,也就是三个Renderer Feature。他们渲染的部分效果如下:很明显的可以看到第一个Feature是画枪不透明的部分,第二个Feature是画的是与枪不透明部分重合的半透明处,第三个Feature画的是与枪不透明部分不重合区域的半透明处。
我们来看第一个Renderer Feature,我们命名为GunOpaques,顾名思义就是画枪上不透明的部分。
因为我们要画整个不透明物体武器,我们要在URP Forward Opaque Pass之前执行,故这里的Event 我们要设置为Before Rendering Opaques。另外Filters 这里,因为我们需要画不透明物体和画First Person Objects层,所以这里我们Queue和LayerMask设置为Opaque和First Person Objects。
我们不需要替换材质,所以Overrides中的Material这里不用选择,勾选Stencil并将Stencil的值设置为1,Compare Function设置为始终返回true,Replace的意思是将参考值1写入缓冲区。FOV的值我们改为40;到这我们GunOpaques就设置完成了。
第二个Renderer Feature GunTransparents渲染与不透明部分重叠的武器的透明部分,有点绕口,如下图所示:
我们来看下Renderer Feature的设置,因为我们是渲染透明物体,所以这里的Event 我们要设置为After Rendering Transparents。Filters 这里设置为Transparents,LayerMask为First Person Objects层。因为要画在不透明物体上的(上一步中枪的不透明部分Stencil我们已经写为1),所以这里的Stencil的Value为1,Compare Function 为Equal。FOV 改为40。GunTransparents设置完成;
第三个Renderer Feature GunTransparentsOverlay渲染武器的透明部分,该部分与不透明部分不重叠,但无论深度如何,始终在场景上进行渲染。
这个与第二个Renderer Feature设置类似,但有一处得说下就是渲染武器的透明部分,而且该部分与不透明部分不重叠,所以这里的Stencil的值没有被在画不透明物体的时候重写为1,故这里的值应该为0。另外无论深度如何,始终在场景上进行渲染,所以这里的Depth Test 我们设置为Always。
最终的效果如下右图所示:
讲到这里的话这个案例就讲完了。我们使用Renderer Feature成功的解决了在内置渲染管线FPS游戏中需要额外摄像机渲染武器的问题,我想通过这两个Renderer Feature的案例大家已经熟悉如何在URP通用渲染管线中使用Renderer Feature了吧!
我在QQ开设了一个学习交流群,欢迎大家加入。任何与URP相关的问题,都可以在群里@我哦。
群名称:Unity URP学习交流群
下一期会带大家手把手写Scriptable Renderer Feature以及更多与URP相关的内容,欢迎大家来Unity社区关注我哦。
以下是本篇文章所用到的技术资料链接:
[1] URP手册
[2] URP官方案例
长按关注
第一时间了解Unity引擎动向,学习最新开发技巧
每一个“在看”,都是我们前进的动力