《Unity Shader入門精要》自學筆記(五)第八章 透明效果
官方API:ShaderLab: Blending
這一章的內容巨多啊,資訊量比五六七章加起來還多
不過整清楚渲染順序、深度測試、深度寫入、透明度測試、透明度混合,以及它們對渲染的影響,這一章理起來也就順了
雜七雜八但是很重要的知識點
深度緩衝區Z-Buffer
儲存螢幕上的每個畫素當前的深度值,值越大,離螢幕越遠
深度測試
將當前片元的深度值與深度緩衝區中的深度值比較,若比深度緩衝區中的值大,則說明這個片元會被之前渲染過的片元擋住,沒有必要再繼續渲染了,所以會被丟棄(當然也可以手工設定遠被捨棄,還是近被捨棄,還是一些其他的判斷標準)
深度寫入ZWrite
當一個片元通過了深度測試,並且pass開啟了深度寫入,這個片元的深度值就會覆蓋深度緩衝區中的深度值;否則不會對深度緩衝區做修改
顏色緩衝區和顏色寫入
通過了各種測試的片元會將自己的顏色存入顏色緩衝區(前提是開啟了顏色寫入)。當有新的片元通過了重重測試,會根據渲染模式來決定,是直接用新片元的顏色覆蓋顏色緩衝區,還是將新老顏色根據透明度做一個混合
透明度測試和透明度混合
透明度測試
沒通過透明度測試,片元也會被直接丟棄。但和深度測試不一樣的是,它沒有緩衝區,只是將片元的透明度和一個設定的值相比較,是否滿足一個設定的條件(< > = ≥ ≤ 等),不滿足直接丟棄
也就是“要麼看得見要麼看不見”的簡單粗暴效果,還會因為浮點數精度問題有明顯的鋸齒
一般會使用Clip()函式:給定引數的任意一個分量是負數,都會捨棄該片元
透明度混合
簡單來講,它要做的就是上面提到的“顏色緩衝區新老顏色按照透明度進行混合”,這個才是比較像真正的透明效果
渲染順序、關閉深度寫入後的一系列填坑操作
渲染順序
就是渲染不同型別物體的順序:背景、不透明物體、透明物體等
unity中準備了5個佇列,為SubShader提供了Queue標籤:
開啟深度寫入的情況下,完全不用關心渲染順序,因為每個片元的覆蓋與否都會經過比較得出結果
但是為了獲得透明效果,需要在渲染透明物體時關閉深度寫入,這個時候就體現了渲染順序的重要:
如果透明物體A和不透明物體B一前一後,先渲染了透明物體A,B來的時候A並沒有把深度值寫入,所以B按照流程理所應當的把自己的顏色整個填進了顏色緩衝區,覆蓋了A的顏色,並且沒有執行透明度混合
如果先渲染了不透明的B,再渲染透明的A的話,A發現自己沒被遮擋後,會執行透明度混合,達到透明的效果
誰讓不透明物體的shader就是不會管這麼多呢,關閉深度寫入和透明度混合只寫在透明物體自己的shader裡呀,那隻能你殿後了鴨
那…
為啥要關閉深度寫入
首先,深度寫入被關閉的是透明物體
因為我們是可以看到透明物體背後的其他物體的,也就是說我們不能直接丟棄深度值大於透明物體的物體
一旦開啟了深度寫入,深度檢測就會丟棄透明物體後面的物體
因此只好關閉深度寫入了,雖然帶來了一系列的麻煩
開啟深度寫入的透明效果
一些情況下就算安排好了渲染順序,還是會有意外發生
因為渲染順序是針對每一個模型的,而每一個模型可以是各種形狀,就導致了模型之間的前後順序並不絕對
而對於一些本身就比較複雜的模型,自己一個人也可以玩出這種錯亂效果
這時可以將物體切分成多個網格,但是還是無法完全避免穿幫,因為它依然不是針對每一個畫素進行深度測試
或者,乾脆在不影響透明度混合的前提下把可愛的深度寫入安回來:
現在的shader是這樣的
SubShader
{
Tags{"Queue" = "Transparent", "IgnoreProjector" = "True", "RenderType" = "Transparentut"}
Pass
{
Tags{"LightMode" = "ForwardBase"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
// ...
}
}
嗯?ZWrite off和Blend命令寫在了Pass裡,那再寫一個ZWrite On的命令在另一個Pass裡不就好了嘛!先做個深度測試,再上色!(代價是需要多渲染一遍,因為增加了一個pass)
SubShader
{
Tags{"Queue" = "Transparent", "IgnoreProjector" = "True", "RenderType" = "Transparentut"}
Pass
{
ZWrite On
ColorMask 0
}
Pass
{
Tags{"LightMode" = "ForwardBase"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
// ...
}
}
效果:
不會錯亂了,但是細節也少了:
自己被自己遮擋的部分完全看不見了,只能看見下面的不透明平面
被另一個透明物體遮擋的部分也看不見了,只能看見下面的不透明平面
這些都是因為被遮擋的片元被深度測試卡掉了
雙面渲染的透明效果 —— Cull命令
上面的透明效果都是隻能看到正面,物體內部和背面的情況完全看不到,是因為引擎自動剔除了物體背面(相對於攝像機的方向)的渲染圖元
想要雙面效果,就要渲染出背面的圖元,unity中要用到Cull指令:
Cull Back | Front | Off
分別代表剔除背面(預設情況)、前面、關閉剔除
對於雙面的透明度測試,只要在Pass內關閉剔除就可以了
但是對於雙面的透明度混合,就要考慮到渲染順序,誰讓萬惡之源是ZWrite Off呢…
由於Pass是按順序執行的,所以可以將背面和正面的渲染分開到先後兩個Pass中,使用Cull Front和Cull Back分別渲染
不過這樣物體之間的順序還是亂的,因為沒有了深度寫入
混合型別:混合因子、混合命令
應該會有很多高階玩法待開發呢
混合因子就是混合命令中的SrcFactor和DstFactor,分別代表源顏色(該片元的顏色)的混合因子和目標顏色(顏色緩衝區中的顏色)的混合因子
表格第三行的命令寫成式子就是:
O
r
g
b
O_{rgb}
Orgb =
S
r
c
F
a
c
t
o
r
SrcFactor
SrcFactor *
S
r
g
b
S_{rgb}
Srgb +
D
s
t
F
a
c
t
o
r
DstFactor
DstFactor *
D
r
g
b
D_{rgb}
Drgb
O
a
O_a
Oa =
S
r
c
F
a
c
t
o
r
A
SrcFactorA
SrcFactorA *
S
a
S_a
Sa +
D
s
t
F
a
c
t
o
r
A
DstFactorA
DstFactorA *
D
a
D_a
Da
表格第二行的命令中SrcFactorA就是SrcFactor,DstFactorA就是DstFactor
混合因子SrcFactor、DstFactor可以是什麼呢
emm其實就是按照目標值&源值、rgb值&alpha值、原值&1-原值、0&1啦…
混合操作BlendOp Operation都有啥?
BlendOp Add就是預設的混合操作,需要改變的話要在指定混合因子前新增BlendOp命令
可以看出Min和Max只與源顏色和目標顏色的rgba值相關,所以在用他們的時候混合因子可以直接指定為One或者Zero
未列出的DirectX混合操作見官方API:ShaderLab: Blending
混合型別有哪些呢?
書中和工程檔案中提供了一些常見的型別
再分開看看
O r g b = S r c A l p h a ∗ S r g b + ( 1 − S r c A l p h a ) ∗ D r g b O a = S r c A l p h a ∗ S a + ( 1 − S r c A l p h a ) ∗ D a \begin{aligned} O_{rgb} = SrcAlpha * S_{rgb} + (1 - SrcAlpha )* D_{rgb}\\ O_a = SrcAlpha * S_a + (1 - SrcAlpha ) * D_a \end{aligned} Orgb=SrcAlpha∗Srgb+(1−SrcAlpha)∗DrgbOa=SrcAlpha∗Sa+(1−SrcAlpha)∗Da
O r g b = ( 1 − D s t C o l o r ) ∗ S r g b + D r g b O a = ( 1 − D s t C o l o r ) ∗ S a + D a \begin{aligned} O_{rgb} = ( 1 - DstColor)* S_{rgb} + D_{rgb}\\ O_a = ( 1 - DstColor)* S_a + D_a \end{aligned} Orgb=(1−DstColor)∗Srgb+DrgbOa=(1−DstColor)∗Sa+Da
O r g b = D s t C o l o r ∗ S r g b O a = D s t C o l o r ∗ S a \begin{aligned} O_{rgb} = DstColor * S_{rgb}\\ O_a = DstColor * S_a \end{aligned} Orgb=DstColor∗SrgbOa=DstColor∗Sa
O r g b = D s t C o l o r ∗ S r g b + S r c C o l o r ∗ D r g b O a = D s t C o l o r ∗ S a + S r c C o l o r ∗ D a \begin{aligned} O_{rgb} = DstColor * S_{rgb} + SrcColor* D_{rgb}\\ O_a = DstColor * S_a + SrcColor* D_a \end{aligned} Orgb=DstColor∗Srgb+SrcColor∗DrgbOa=DstColor∗Sa+SrcColor∗Da
O = ( m i n ( S r , D r ) , m i n ( S g , D g ) , m i n ( S b , D b ) , m i n ( S a , D a ) ) \begin{aligned} O = (min(S_r, D_r), min(S_g, D_g), min(S_b, D_b), min(S_a, D_a)) \end{aligned} O=(min(Sr,Dr),min(Sg,Dg),min(Sb,Db),min(Sa,Da))
O = ( m a x ( S r , D r ) , m a x ( S g , D g ) , m a x ( S b , D b ) , m a x ( S a , D a ) ) \begin{aligned} O = (max(S_r, D_r), max(S_g, D_g), max(S_b, D_b), max(S_a, D_a)) \end{aligned} O=(max(Sr,Dr),max(Sg,Dg),max(Sb,Db),max(Sa,Da))
O r g b = ( 1 − D s t C o l o r ) ∗ S r g b + D r g b O a = ( 1 − D s t C o l o r ) ∗ S a + D a \begin{aligned} O_{rgb} = (1 - DstColor)* S_{rgb} + D_{rgb}\\ O_a = (1 - DstColor)* S_a + D_a \end{aligned} Orgb=(1−DstColor)∗Srgb+DrgbOa=(1−DstColor)∗Sa+Da
O r g b = S r g b + D r g b O a = S a + D a \begin{aligned} O_{rgb} = S_{rgb} + D_{rgb}\\ O_a = S_a + D_a \end{aligned} Orgb=Srgb+DrgbOa=Sa+Da
總結
感覺自己的筆記記得越來越亂了…果然知識多了就要勤記著點…
透明度混合這裡有很多可以做實驗的地方,各種混合操作的效果還不是特別有印象,抽空要多玩玩這裡,回來補一下筆記
這一章終於開始更多的接觸到tags啦,以及多個pass相互協助的使用,也讓shader變得有趣起來了,後面的學習一定也會更有意思的吼吼吼!
也算是終於好好的理解一把ps的圖層型別哈哈哈
相關文章
- Unity Shader 入門精要 筆記(1)Unity筆記
- Unity學習筆記--入門Unity筆記
- Unity3D學習筆記3——Unity Shader的初步使用Unity3D筆記
- Unity3D 透明物體ShaderUnity3D
- Re:《Unity Shader入門精要》13.3全域性霧效--如何從深度紋理重構世界座標Unity
- TypeScript 入門自學筆記(一)TypeScript筆記
- Electron小白入門自學筆記(一)筆記
- Unity Shader 實現雨天的水面漣漪效果Unity
- uni-app小白入門自學筆記(一)APP筆記
- uni-app小白入門自學筆記(二)APP筆記
- Unity的Shader學習筆記(09)[20/12/24_週四][33-36]Unity筆記
- Shader從入門到跑路:螢幕後處理效果
- Shader從入門到跑路:實作螢幕扭曲效果
- Unity Shader之磨砂玻璃與水霧玻璃效果Unity
- Unity Shader 00 - 梳理 Unity Shader 的基本結構Unity
- TypeScript 入門自學筆記 — 型別斷言(二)TypeScript筆記型別
- Unity 的 Surface Shader有關記錄Unity
- Unity Shader基於視差對映的雲海效果Unity
- git入門學習筆記Git筆記
- Docker入門學習筆記Docker筆記
- TS入門學習筆記筆記
- 【PostgreSQL】入門學習筆記SQL筆記
- 自學PHP筆記(五) PHP運算子PHP筆記
- unity學習筆記(三)Unity筆記
- unity學習筆記(一)Unity筆記
- Unity3D筆記五 快捷鍵Unity3D筆記
- 五筆輸入法入門
- HTML入門學習筆記(二)HTML筆記
- React入門指南(學習筆記)React筆記
- pandas 學習筆記 (入門篇)筆記
- Go 入門指南學習筆記Go筆記
- MySQL學習筆記---入門使用MySql筆記
- Dubbo學習筆記(一) 入門筆記
- JavaScript入門-學習筆記(一)JavaScript筆記
- JavaScript入門學習學習筆記(上)JavaScript筆記
- JavaScript學習筆記1—快速入門JavaScript筆記
- iOS學習筆記39 ReactiveCocoa入門iOS筆記React
- redis學習筆記1: Redis入門Redis筆記