查看原文
其他

URP系列教程 | 如何使用多个Renderer Feature来实现角色透视效果

李鹏鹏 Unity官方平台 2023-03-15
URP 系列教程又开更啦~鹏鹏老师这次将分享如何使用多个 Renderer Feature 来实现角色透视效果。


我们知道 URP 的 Renderer Feature 支持用户向 URP Renderer 添加额外的渲染通道,从而允许我们进行自定义渲染的顺序、渲染的对象或者材质等。使用 Renderer Feature,我们可以实现多 pass 的效果,比如物体的描边效果、以及自定义一些后处理效果等等,我今天就手把手带大家使用多个 Renderer Feature 来实现角色的透视效果


具体是一个什么样的效果呢?如下图所示我们使用 URP 的 Renderer Feature 实现当角色位于 GameObjects(建筑物)背后时,Unity 会使用不同的材质绘制角色,从而表现出一种透视的视觉效果。



首先我们创建一个 URP Asset,将其重命名为 OcclusionDemoCompleted(当然这个名字你可以自己发挥),然后将其赋给 Project Settings > Graphics > Scriptable Render Pipeline Settings(如下图所示)。



接着创建一个材质 Dither,并使用 Shader Graph 创建一个屏幕扰动的 Shader,并将其命名为 ScreenDitherShader。颜色我设置为黄色,把这个 Shader 赋给这个材质 Dither,当角色位于 GameObject 后,我们后面会用 Renderer Feature 调用这个材质 Dither 去替换角色本身的材质 MAT_Mage_Blue。



这个案例里我们实现使用了两个 Render Object Renderer Feature:一个用于绘制位于场景中其他游戏对象(如建筑)后面的角色部分,另一个用于绘制位于场景中其他游戏对象(如建筑)前面的角色部分。


我们先来创建用于绘制在建筑后面时角色部分的 Renderer Feature


首先我们选择之前创建的 UnityOcclusionRenderer,在 Inspector 中,单击 Add Renderer Feature 并选择 Render Objects。选择名称字段并输入新渲染器功能的名称 Dither(因为在建筑背后,角色表现出扰动的效果所以名字命名为Dither)。



我们使用 Layer 层来过滤要渲染的游戏对象,创建一个新的 Layer 层,并将其重命名为 Character。


在 Dither Renderer Feature  中,在 Filters > Layer Mask 中,选择 Character。这样的话,Dither Renderer Feature 仅渲染这个 Layer 中的游戏对象 Character。然后在 Overrides > Material 中,选择 Dither 。那么 Dither Renderer Feature 就会使用设置的材质覆盖游戏对象的正常的材质。



我们的预期效果是仅当角色位于其他游戏对象之后时,Dither Renderer Feature 才使用 Dither 材质渲染角色。所以我们要进行深度检测 Depth Test (深度信息是用来决定哪些像素离摄像机更近,我们这里使用深度测试DepthTest来决定当前像素是否被绘制),我们勾选“Depth”复选框,并将“Depth Test 深度测试”属性设置为“Greater”(大于)。


这样设置也就意味着,Dither Renderer Feature 仅在角色的深度值(深度值的范围在0~1之间,值越小表示越靠近摄像机,值越大表示越远离摄像机)大于另一个物体的深度值(也就意味着角色位于另一个游戏对象后面时)才使用材质渲染角色。



但是现在我们遇到一个问题是:因为角色的某些部分也会遮挡角色本身。所以 Dither 材质会替换角色的某些部分。如下右图所示。这不是我们预期的结果。



为什么会发生这种情况呢?执行 Dither Renderer Feature 时,Unity 使用深度测试属性中指定的条件执行深度测试。与截图中所示的情况类似,较大的胶囊遮挡了较小胶囊的一部分,并且对于较小胶囊的那部分通过了深度测试。那么 Renderer Feature 会覆盖该部件的材质。我们的角色的遮挡也类似;所以出现了这种自透明效果情况的发生。



那么我们要怎么解决这个问题?接下来我们就来看下如何避免此类行为确保 Unity 使用适当的材质绘制角色的所有部分。


 在 URP Renderer 中,在Filtering > Opaque Layer Mask 中,清除 Character 图层旁边的复选标记。现在 Unity 不会渲染角色,除非它位于 GameObject 后面。但这个还不是我们需要的效果(如下图所示)。



 然后我们添加一个新的 Renderer Feature,并将其命名为 Character. 这就是我们前面提到的那个用于绘制位于场景中其他游戏对象(如建筑)前面的角色部分的 Renderer Feature 。


 在 Character Renderer Feature 中,在 Filters > Layer Mask 中,选择 Character 图层(因为两个Renderer Feature 都是渲染角色的)。


我们看下效果发现:即使角色在游戏对象后面,Unity 也会使用材质渲染角色。



为什么会发生这种状况呢?发生这种情况是因为在 Dither Renderer Feature 中勾选了 Write Depth( Write Depth:定义Renderer Feature是否在渲染对象时更新深度缓冲区)将深度值更新重写深度缓冲区。角色在建筑背后被 Dither 材质渲染也就是说角色的深度值已经变化。这个时候在执行 Character Renderer Feature 当然会被再次渲染掉。


所以我们要做就是取消勾选 Write Depth 选项。不需要重写深度缓冲区。



 在 Overrides > Depth 中,清除 Write Depth 复选框。Dither Renderer Feature 将不会更改深度缓冲区,并且当角色位于建筑游戏对象之后时, Character Renderer Feature 也不会绘制角色。


到这里的话,当角色在建筑 GameObjects 之后时,Unity 会使用 Dither Material 绘制角色轮廓的效果就已经完成。



Ok,到这里的话,我们使用两个 Renderer Feature 实现了角色的透视效果。


最后,在今年我会开启 URP 系列教程(基本功能)、URP 最新功能系列教程,一起打造元宇宙系列教程等多个 Channels。欢迎大家来 Unity 中文课堂注我的个人账号。


Unity 中文课堂,按作者搜“李鹏鹏”




长按关注

Unity 官方微信

第一时间了解Unity引擎动向,学习最新开发技巧




 每一个“在看”,都是我们前进的动力 

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存