GLSL 程式設計/Unity/順序無關透明度

本教程涵蓋順序無關混合。
它繼續討論“透明度”部分,並解決標準透明度的一些問題。如果你沒有讀過那個教程,你應該先讀一下。

如“透明度”部分所述,混合結果通常(特別是對於標準 alpha 混合)取決於三角形渲染的順序,因此如果三角形沒有從後到前排序(它們通常沒有),就會導致渲染偽像。術語“順序無關透明度”描述了各種避免此問題的技術。其中一項技術是順序無關混合,即使用不依賴於三角形光柵化順序的混合方程。有兩種基本可能性:疊加混合和相乘混合。
疊加混合的標準示例是本節中的影像中的雙重曝光:顏色被新增,以至於不可能(或至少非常困難)說出照片拍攝的順序。疊加混合可以用“透明度”部分中介紹的混合方程來表徵
vec4 result = SrcFactor * gl_FragColor + DstFactor * pixel_color;
其中SrcFactor和DstFactor由 Unity 的 ShaderLab 語法中的行確定
Blend {SrcFactor 的程式碼} {DstFactor 的程式碼}
對於疊加混合,DstFactor 的程式碼必須為One,SrcFactor 的程式碼不能依賴於幀緩衝區中的畫素顏色;也就是說,它可以是One、SrcColor、SrcAlpha、OneMinusSrcColor或OneMinusSrcAlpha。
一個例子是
Shader "GLSL shader using additive blending" {
SubShader {
Tags { "Queue" = "Transparent" }
// draw after all opaque geometry has been drawn
Pass {
Cull Off // draw front and back faces
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend SrcAlpha One // additive blending
GLSLPROGRAM
#ifdef VERTEX
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
#endif
#ifdef FRAGMENT
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 0.3);
}
#endif
ENDGLSL
}
}
}
攝影中相乘混合的一個例子是使用多個均勻的灰色濾鏡:濾鏡放在相機上的順序對於影像的最終衰減無關緊要。就三角形的光柵化而言,影像對應於三角形光柵化之前幀緩衝區的內容,而濾鏡對應於三角形。
在使用以下行在 Unity 中指定相乘混合時
Blend {SrcFactor 的程式碼} {DstFactor 的程式碼}
SrcFactor 的程式碼必須為Zero,DstFactor 的程式碼必須依賴於片段顏色;也就是說,它可以是SrcColor、SrcAlpha、OneMinusSrcColor或OneMinusSrcAlpha。一個典型的使用片段的 alpha 分量指定的透明度來衰減背景的示例將使用OneMinusSrcAlpha作為DstFactor 的程式碼
Shader "GLSL shader using multiplicative blending" {
SubShader {
Tags { "Queue" = "Transparent" }
// draw after all opaque geometry has been drawn
Pass {
Cull Off // draw front and back faces
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend Zero OneMinusSrcAlpha // multiplicative blending
// for attenuation by the fragment's alpha
GLSLPROGRAM
#ifdef VERTEX
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
#endif
#ifdef FRAGMENT
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 0.3);
// only A (alpha) is used
}
#endif
ENDGLSL
}
}
}
最後,將相乘混合用於衰減背景並將疊加混合用於新增三角形的顏色組合在一個著色器中是有意義的,方法是組合上面介紹的兩個通道。如果忽略三角形網格顏色本身的衰減,這可以被認為是對小透明度,即小的 alpha 值的 alpha 混合的近似。
Shader "GLSL shader using order-independent blending" {
SubShader {
Tags { "Queue" = "Transparent" }
// draw after all opaque geometry has been drawn
Pass {
Cull Off // draw front and back faces
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend Zero OneMinusSrcAlpha // multiplicative blending
// for attenuation by the fragment's alpha
GLSLPROGRAM
#ifdef VERTEX
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
#endif
#ifdef FRAGMENT
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 0.3);
// only A (alpha) is used
}
#endif
ENDGLSL
}
Pass {
Cull Off // draw front and back faces
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend SrcAlpha One // additive blending to add colors
GLSLPROGRAM
#ifdef VERTEX
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
#endif
#ifdef FRAGMENT
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 0.3);
}
#endif
ENDGLSL
}
}
}
請注意,兩個通道的順序很重要:首先衰減背景,然後新增顏色。
恭喜你,你已經完成了本教程。我們已經瞭解了
- 什麼是順序無關透明度和順序無關混合。
- 兩種最重要的順序無關混合型別是什麼(疊加和相乘)。
- 如何實現疊加混合和相乘混合。
- 如何將兩個通道組合用於疊加和相乘混合,以實現對 alpha 混合的順序無關近似。
如果你仍然想了解更多