總結一下Shader開啟透明渲染后的一些顯示問題的解決方案,考慮Zwrite,Ztest,Queue這三個屬性的設置問題。
首先需要記住的是:
對於不透明物體,渲染的正確順序是從前往后;
對於半透明物體。渲染的順序是從后往前。
這樣才能實現正確的渲染輸出。
注意:Alpha Test,Alpha to Coverage不在討論之列。這里涉及到的是使用Alpha Blend的物體。
其次是,Unity Shader中需要注意的三個屬性。
Zwirte:是否開啟深度緩存,默認為On。
Ztest:深度測試的模式,默認為Lequal(小於等於)。
Queue:渲染隊列,默認為Geometry。
常規來說:
對於不透明物體,默認的設置為Zwrite On,Ztest Lequal,Queue=“Geometry”。
對於半透明物體,默認的設置為Zwrite Off,Ztest Lequal,Queue=“Transparent”。
對於半透明物體,這樣的設置在一般的情況下是沒有問題的,但是在某些情況下會出現問題。
先解釋一下相關的概念:
Queue:最好理解,也就是物體的在渲染隊列中的順序。
Zwrite On:會開啟深度緩存和深度測試,即在繪制物體表面上的一個像素時,會對像素的深度值和深度緩存中對應點的值進行比較,如果該像素的深度值小於或等於(Ztest Lequal)深度緩存中的值,就用該像素的顏色和深度替換掉原有的像素。
Zwrite開啟之后,圖形渲染將按照深度測試的結果來進行,不會因為渲染順序不一致而導致前面的物體被后面的物體覆蓋的問題。
半透明物體關閉了Zwrite,這時候渲染隊列對於正確的顯示就十分重要了。必須嚴格的按照后面的先渲染,前面的后渲染的順序,否則會出現不正確的遮擋關系。
那么回到上面的問題,什么情況下半透明物體的默認設置表現不正確?
舉個簡單的例子,十字交叉的面片草渲染,通常情況下會使用Alpha Test的Shader。但是Alpha Test並不支持抗鋸齒,所以有時候考慮到鋸齒問題OR性能問題使用Alpha Blend。
如果使用默認設置,那么會觀察到交叉的重疊效果不正確。這是因為Zwrite Off,兩個面片按照先后順序分別渲染,導致錯誤的重疊效果。
相反,如果開啟了Zwrite,則會發現,由於開啟了深度緩存測試,前面的透明像素成功的替換掉后面的不透明像素。導致前面面片的透明像素沒有與后面的不透明像素混合,而是直接顯示了背景像素。
對於UI之上有模型使用半透明材質,導致與場景進行半透明混合而不是與UI進行半透明混合的解決方案則是:使用腳本調整模型的Sorting Order,使其略大於UI組件Canvas的Sorting Order即可。
除了Shader層面的解決方式,半透明還可以通過修改頂點ID的方式來進行渲染順序的修改,這里的具體方式不詳細說明。