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的具體操作流程:

因爲ZWrite默認值爲On,ZTest默認值爲LEqual,所以這很好地解釋了爲什麼在unity中,距離相機近的東西會阻擋住距離相機遠的東西。如果我們先繪製一個距離較近的物體,再繪製距離較遠的物體,則距離遠的物體因爲後繪製,會把距離近的物體覆蓋掉,這時我們可以通過修改ZWrite和ZTest來改變物體的遮擋關係

所以對於透明物體的渲染,一般要關閉掉ZWrite,比如Unity中用於渲染Sprite的默認SpriteDefault材質的Shader:

加深對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,但是當你實際使用的時候,怪事發生了:

從FrameDebugger中可以看到,對於不透明物體的渲染,skybox是在opaque的最後渲染,從而減少OverDraw。這尼瑪不跟RenderQueue寫的1000衝突麼?!Google一頓操作,結果是這樣:

 

 

總結來說就是:Unity關於Skybox部分的文檔好久沒有更新了,目前Skybox應該是RenderQueue 值爲2500.5時渲染,在Opaque和AlphaTest之後,Transparent之前。

Unity這個文檔證明了這個說法:https://docs.unity3d.com/Manual/GraphicsCommandBuffers.html?_ga=2.53580588.563516390.1589165101-117244140.1588818896

 

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大小精確控制排序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章