Shader筆記——7.透明效果
不透明物體
渲染不透明物體時,即使不去考慮不透明的物體Opaque之間的渲染順序,也可以得到正確的渲染結果,是由於強大的深度緩衝Depth Buffer/Z-Buffer的存在,深度緩衝用於解決片元可見性問題,即物體哪些部分被渲染在前面,哪些部分被遮擋
-
深度緩衝的基本思想是根據深度快取中的值來判斷當前片元距離攝像機距離的遠近,當進行一個片元的渲染時,需要把它的深度值和當前已經存在的深度快取中的值進行比較(如果開啟了深度測試ZTest On)
-
如果它的值距離攝像機的距離更遠,則說明它不能被渲染到螢幕上將被捨棄;
-
如果它的值相比已存在的深度快取中的深度值距離攝像機的距離較小,則說明它距離攝像機距離更近,這個片元便會覆蓋掉此時顏色緩衝中的畫素值,並把它的深度值更新到深度快取中(如果開啟了深度寫入ZWrite On)
透明物體
渲染透明物體時,不僅要關注渲染圖元上每個片元的顏色值和深度值,還要關注每個片元的透明度屬性,通常有兩種方式實現,透明度測試Alpha Test以及透明度混合Alpha Blending
-
透明度測試Alpha Test,使用透明度測試時,根據透明度來捨棄一些片元,不需要關閉深度寫入,但是,渲染出來的效果很極端,不能渲染出真正的透明效果
-
透明度混合Alpha Blending,使用時需要關閉深度寫入ZWrite Off,所以透明度混合時,渲染順序十分重要,而且不透明物體之間的渲染順序也需要正確設定
所以渲染引擎一般都會先對物體排序後再進行渲染,先渲染所有不透明物體,開啟它們的深度測試和深度寫入;再把半透明物體按距離攝像機的遠近進行排序,由遠及近的順序渲染這些半透明的物體,開啟深度測試但是關閉深度寫入
Unity Shader的渲染順序
在SubShader中使用“Queue”標籤來控制渲染順序,指定此時渲染的物體屬於哪一個渲染佇列,Unity在內部使用一系列的整數索引來表示每個渲染佇列,索引數越小就越早渲染
渲染佇列包括的值有:
- Background:1000。這種型別的順序會排在所有物體的前面。例如天空盒。
- Geometry:2000。所有不透明物體及大多數物體使用這個型別。
- AlphaTest:2450。使用Alpha Test的物體使用這個型別的渲染順序。它被排在不透明物體的渲染後面。
- Transparent:3000。排在Geometry和AlphaTest後渲染。所有alpha混合的物體都應該選擇這個型別。
- Overlay:4000。這一類是最後渲染的,比前面所有型別都要置後,例如鏡頭光暈。
- 使用者自定義值:比如”Queue”=”Geometry+10”。
例需要使用透明度測試實現透明效果:
SubShader{
Tags{"Queue" = "AlphaTest"
"IgnoreProjector" = "True"
"RenderType" = "TransparentCutout"
}
Pass{
Tags{"LightMode" = "ForwardBase"}
//code elide
}
}
例通過透明度混合實現透明效果:
SubShader{
Tags{"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
}
Pass{
Tags{"LightMode" = "ForwardBase"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
//code elide
}
}
透明度測試Alpha Test
一般在片元著色器中使用clip函式來進行透明度測試,只要一個片元的透明度不滿足條件(小於某個閾值),那麼這個片元就會被捨棄,處理透明度測試時的操作跟對待普通不透明的物體幾乎是一樣的,只是透明度測試在片元著色器中增加了對透明度判斷並裁剪片元的程式碼
clip函式是CG中的一個函式:
void clip(float4 x){
if(any(x < 0>)){
discard;
}
}
透明度混合Alpha Blending
使用Unity提供的Blend混合命令 Blend SrcFactor DstFactor 開啟混合,並設定混合因子,源顏色(片元產生的顏色)乘以SrcFactor,目標顏色(顏色緩衝中的顏色)乘以DstFactor,兩者相加後在存入顏色緩衝中
Blend SrcAlpha OneMinusSrcAlpha
使用透明度混合必須要開啟Blend,只有開啟了Blend命令,在片元著色器中設定的透明通道才有意義,未開啟Blend命令的話,設定的透明度將對片元的透明效果沒有任何影響。
透明度混合的Shader程式碼和透明度測試的程式碼也幾乎一樣,只是移除了該片元著色器中的透明度判斷、裁剪片元程式碼,設定了該片元著色器中的透明通道(紋理畫素的透明通道和引數_AlphaScale的乘積)
REF
文件:
https://docs.unity3d.com/Manual/class-RenderTexture.html
書籍:
OpenGL寶典、Unity Shader入門