半透明渲染方式

渲染順序一般是先渲染不透明物體,然後才到透明物體。Depth Test沒有通過的片元,會被捨棄,通過了Depth Test的片元,進行混合計算,且不將深度寫進z-buffer中。假設寫入了z-buffer,那麼在下一次渲染的物體是在該深度後但在不透明物體前時,就會因為深度測試,導致被捨棄。所要z-buffer中保存的只有不透明物體的深度。因為這個原因,也導致渲染順序非常重要。

即使場景中都只有透明物體,渲染順序也非常重要,愈後的物體應被先渲染,不然可能出現物體前後出現反轉的效果。基於這個問題,渲染引擎一般都會先對物體進行排序,再渲染。常用的方法是

  1. 先渲染所有不透明物體,並開啟它們的深度測試和深度寫入
  2. 把半透明物體按它們距離攝像機的遠近進行排序,然後按照從後往前的順序渲染,開啟深度測試,關閉深度寫入

第2項在電腦中並不好做,因為有一些交叉的物體,可能有一端是在另一個物體的前面,但在另一端卻在另一個物體的後面。也就是說,兩個物體之間同時存在: 在另一個物體的前與後的狀態下。

Untitled

像圖中的物體的遠近是不可判斷的。這種問題的解決方法通常也是分割網格。

Unity Shader的渲染順序

Unity為了解決渲染順序的問題提供了渲染隊列 (render queue)。可以使用SubShader的Queue標簽來決定歸於哪個渲染隊列。Queue愈小愈早被渲染。

Name Index Description
Background 1000 會在任何其他隊列之前被渲染,通常使用該隊列淶渲染那些需要繪制在背景上的物體。
Geometry 2000 默認的渲染隊列,大多數物體都使用這個隊列。
AlphaTest 2450 需要透明度測試的物體使用這個隊列。在Unity 5中它從Geometry隊列中被單獨分出來,這是因為在所有不透明物體渲染之後再渲染它們會更加高效。
Transparent 3000 這個隊列中的物體會在所有Geometry和AlphaTest物體渲染後,再按從後往前的順序進行渲染。任何使用了透明度混合(例如關閉深度寫入的Shader)的物體都應該使用該隊列。
Overlay 4000 用於實現一些疊加效果。
SubShader {
	Tags { "Queue" = "AlphaTest" }
	Pass {
		...
	}
}

SubShader {
	Tags { "Queue" = "Transparent" }
	Pass {
		ZWrite Off
		...
	}
}

透明度測試