Unity 中渲染顺序的理解以及一些坑点 以及2.5D游戏中的渲染排序解决方案

1.ZTest & ZWrite

ZTest:深度测试,开启后测试结果决定片元是否被舍弃,可配置 
ZWrite:深度写入,开启后决定片元的深度值是否写入深度缓冲,可配置

ZTest可设置的测试规则:

ZTest Less:深度小于当前缓存则通过
ZTest Greater:深度大于当前缓存则通过
ZTest LEqual:深度小于等于当前缓存则通过
ZTest GEqual:深度大于等于当前缓存则通过
ZTest Equal:深度等于当前缓存则通过
ZTest NotEqual:深度不等于当前缓存则通过
ZTest Always:不论如何都通过
注意,ZTest Off等同于ZTest Always,关闭深度测试等于完全通过。

ZWrite配置: 
ZWrite On 深度写入开启 ZWrite Off 深度写入关闭

ZTest和ZWrite发生在逐片元操作过程,处于片元着色后,最终屏幕输出前。ZTest与ZWrite的具体操作流程:

Unity 中渲染顺序的理解以及一些坑点 以及2.5D游戏中的渲染排序解决方案_第1张图片

因为ZWrite默认值为On,ZTest默认值为LEqual,所以这很好地解释了为什么在unity中,距离相机近的东西会阻挡住距离相机远的东西。如果我们先绘制一个距离较近的物体,再绘制距离较远的物体,则距离远的物体因为后绘制,会把距离近的物体覆盖掉,这时我们可以通过修改ZWrite和ZTest来改变物体的遮挡关系

所以对于透明物体的渲染,一般要关闭掉ZWrite,比如Unity中用于渲染Sprite的默认SpriteDefault材质的Shader:

Unity 中渲染顺序的理解以及一些坑点 以及2.5D游戏中的渲染排序解决方案_第2张图片

加深对ZTest & ZWrite的理解,可以参考这篇文章的测试部分,把各例子理解明白非常有帮助。

https://www.jianshu.com/p/9137ee354dbd

2.Unity渲染顺序

能够影响渲染顺序的因素有:

  • Camera Depth:    相机组件上设置的相机深度,深度越大越靠后渲染。
  • Sorting Layer:     在Tags & Layers设置中可见
  • Order In Layer:    相对于Sorting Layer的子排序,用这个值做比较时只有都在同一层时才有效。
  • RenderQueue:     Shader中对Tags设置的“Queue”。
  • 物体距离相机的距离,ZDepth值

下面是结果:
1、Camera Depth
永远最高。Camera Depth小的一定先进渲染管线。

2、当Sorting Layer和Order In Layer不相同时

  • 当两个材质使用了不同的RenderQueue,且这两个RenderQueue都在[0~2500]或[2501~5000]时,SortingLayer和OrderInLayer的排序生效。
  •  当两个材质使用了不同的RenderQueue,且这两个RenderQueue分别在[0~2500]和[2501~5000]时,则一定会按照RenderQueue绘制,无视SortingLayer、OrderInLayer的排序。

3、当Sorting Layer和Order In Layer相同时

  • RenderQueue不相等:

        RenderQueue小的先进渲染管线。

  •  RenderQueue 相等

        RenderQueue 2500以下,由近到远排序优先 (不透明)

        RenderQueue 2500以上, 由远到近排序优先  (透明)

说明一下:2500是关键值,它是透明跟不透明的分界点,因此我们考虑层级的时候要注意着点:renderqueue > 2500的物体绝对会在renderqueue <= 2500的物体前面,即渲染时renderqueue大的会挡住renderqueue小的,不论它的sortingLayer和sortingOrder怎么设置都是不起作用的。知道了这点,其他的就很好理解了。当两个的RenderQueue都在同一侧时,在SortingLayer高的绝对会在sortingLayer前面,无视renderqueue跟soringOrder,只有在sortingLayer相同的前提下,soringOrder高的会在sortingOrder低的前面,无视renderqueue。当sortingLayer跟sortingOrder相同时,才看renderqueue的高低,高的在前面。

总结下Unity影响渲染顺序各参数的优先级

如果物体的RenderQueue在2500的同一侧:

Camera DepthSorting Layer > Order In Layer > RenderQueue > 距离相机的距离

如果物体的RenderQueue在2500的不同侧:

Camera DepthRenderQueue > Sorting Layer > Order In Layer > 距离相机的距离

3.Unity中的一个坑

Properties Value 渲染队列描述 说明
Background 1000 This render queue is rendered before any others. 这个队列通常被最先渲染(比如 天空盒)。
Geometry 2000 Opaque geometry uses this queue. 这是默认的渲染队列。它被用于绝大多数对象。不透明几何体使用该队列。
AlphaTest 2450 Alpha tested geometry uses this queue. 需要开启透明度测试的物体。Unity5以后从Geometry队列中拆出来,因为在所有不透明物体渲染完之后再渲染会比较高效。
GeometryLast 2500 Last render queue that is considered “opaque”. 所有Geometry和AlphaTest队列的物体渲染完后
Transparent 3000 This render queue is rendered after Geometry and AlphaTest, in back-to-front order. 所有Geometry和AlphaTest队列的物体渲染完后,再按照从后往前的顺序进行渲染,任何使用了透明度混合的物体都应该使用该队列(例如玻璃和粒子效果)
Overlay 4000 This render queue is meant for overlay effects. 该队列用于实现一些叠加效果,适合最后渲染的物体(如镜头光晕)。

从Unity文档中这个图我们可以看出来,Background理应最先被渲染,Unity中的skybox 应该属于这个renderqueue,但是当你实际使用的时候,怪事发生了:

Unity 中渲染顺序的理解以及一些坑点 以及2.5D游戏中的渲染排序解决方案_第3张图片

从FrameDebugger中可以看到,对于不透明物体的渲染,skybox是在opaque的最后渲染,从而减少OverDraw。这尼玛不跟RenderQueue写的1000冲突么?!Google一顿操作,结果是这样:

Unity 中渲染顺序的理解以及一些坑点 以及2.5D游戏中的渲染排序解决方案_第4张图片

Unity 中渲染顺序的理解以及一些坑点 以及2.5D游戏中的渲染排序解决方案_第5张图片 

 Unity 中渲染顺序的理解以及一些坑点 以及2.5D游戏中的渲染排序解决方案_第6张图片

总结来说就是:Unity关于Skybox部分的文档好久没有更新了,目前Skybox应该是RenderQueue 值为2500.5时渲染,在Opaque和AlphaTest之后,Transparent之前。

Unity这个文档证明了这个说法:https://docs.unity3d.com/Manual/GraphicsCommandBuffers.html?_ga=2.53580588.563516390.1589165101-117244140.1588818896

Unity 中渲染顺序的理解以及一些坑点 以及2.5D游戏中的渲染排序解决方案_第7张图片

 

4. 2.5D游戏渲染排序解决方案

上边总结了Unity中渲染顺序的相关知识,那利用这些知识,可以实现2D游戏中景深以及排序的问题,初步总结了几种方案:

1.Order In Layer 

通过设置Order In Layer 为不同的值来进行排序,缺点是需要自定义一套标准来决定物体的Order In Layer值 

下边这个插件用的是这个原理

https://assetstore.unity.com/packages/tools/sprite-management/isometric-toolkit-33032

2.用Shader自定义修改ZDepth

通过自己设置Shader中的ZDepth来达到排序的目的,也就是说Sprite在场景中的Z值都一样,通过制定一套标准,来人为定义物体的ZDepth值 

下边这个插件用的是这个原理

https://assetstore.unity.com/packages/templates/systems/2-5d-isometric-engine-106321

3.利用Z轴,实际就是ZDepth

在场景中把各个Sprite摆放位置根据前后关系设置Z轴位置,这样2D游戏也可以拥有ZDepth的信息,从而可以正确渲染 

4.修改UnityProject 的设置

 改为Y轴为排序轴,这种方法不用考虑Z轴,完全根据Sprite的y轴大小设置,非常简便。我是用的这种方式,暂时的缺点是无法根据sprite大小精确控制排序。

你可能感兴趣的:(GPU,and,Graphics)