模板測試 發(fā)生在片元著色器之后的逐片元操作階段:
透明度測試——>模板測試——>深度測試——>透明度混合
前言
在計算機圖形學(xué)中,透明度測試(Alpha Test)是一種常用的技術(shù),用于在渲染過程中根據(jù)像素的Alpha值進行裁剪或者過濾。通過透明度測試,可以實現(xiàn)在渲染物體時只顯示符合一定透明度要求的像素,從而達到特定的視覺效果。本篇博客將介紹透明度測試在Shader中的應(yīng)用。
一、什么是透明度測試?
1. 透明度測試的工作原理
透明度測試是一種在渲染過程中根據(jù)像素的Alpha值進行裁剪或過濾的技術(shù)。在渲染物體時,每個像素都有一個Alpha值,用來表示其透明度。透明度測試通過比較像素的Alpha值與設(shè)定的閾值,來決定是否保留該像素或者丟棄該像素。通常情況下,當(dāng)像素的Alpha值大于等于閾值時,該像素會被保留,否則會被丟棄。
透明度測試的原理很簡單,即在片元著色器中根據(jù)像素的Alpha值進行判斷,并通過discard語句來丟棄不符合條件的像素。具體步驟如下:
片元著色器中獲取紋理的Alpha值。
將獲取的Alpha值與設(shè)定的閾值進行比較。
如果Alpha值大于等于閾值,則保留該像素,否則丟棄該像素。
2. 透明度測試優(yōu)缺點
優(yōu)點:
簡單高效:透明度測試是一種簡單高效的技術(shù),能夠在渲染過程中快速地根據(jù)Alpha值進行裁剪,節(jié)省計算資源。
適用范圍廣:透明度測試適用于各種場景和物體,可以用來實現(xiàn)各種透明效果
缺點:
硬邊緣:透明度測試會導(dǎo)致像素的邊緣出現(xiàn)硬邊緣,不夠平滑自然。
Alpha混合效果差:由于透明度測試是丟棄像素而不是混合像素,因此在某些情況下會導(dǎo)致Alpha混合效果不理想
3. 透明度測試?yán)龍D

二、使用步驟
- Shader 屬性定義
// 定義屬性
Properties {
//主紋理貼圖
_MainTex("Main Texture", 2 D) = "white" {}
// 漫反射顏色屬性,默認(rèn)白色
_Diffuse("Diffuse Color", Color) = (1, 1, 1, 1)
// Alpha裁剪閾值
__Cutoff("Alpha Cutoff", Range(0,1)) = 0.5
}
- SubShader 設(shè)置
SubShader
{
Tags
{
"Queue" = "AlphaTest" // 渲染隊列為AlphaTest
"IgnoreProjector" = "True" // 忽略投影
}
LOD 100 // 細(xì)節(jié)級別
}
SubShader 定義了一組渲染設(shè)置,包括標(biāo)簽和細(xì)節(jié)級別。在這里,我們將渲染隊列標(biāo)簽設(shè)置為 “AlphaTest”,并且忽略投影
- 渲染 Pass
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 包含Unity CG庫
#include "UnityCG.cginc"
// 包含光照CG庫
#include "Lighting.cginc"
// 漫反射顏色屬性
fixed4 _Diffuse;
// Alpha裁剪閾值
float _Cutoff;
// 主紋理貼圖
sampler2D _MainTex;
float4 _MainTex_ST;
}
這里開始了渲染 Pass 部分。在這里,我們使用了 CGPROGRAM 指令來聲明頂點著色器和片元著色器函數(shù)。#pragma vertex vert 和 #pragma fragment frag分別指定了頂點著色器函數(shù)和片元著色器函數(shù)的名稱。
然后,我們包含了 UnityCG.cginc 和 Lighting.cginc,它們提供了許多有用的函數(shù)和宏,用于簡化編寫 Shader。
- 定義結(jié)構(gòu)體和頂點著色器函數(shù)
// 定義結(jié)構(gòu)體:從頂點到片段的數(shù)據(jù)傳遞
struct v2f {
float4 vertex: SV_POSITION; // 頂點位置
fixed3 worldNormal: TEXCOORD0; // 世界空間法線
fixed3 worldPos: TEXCOORD1; // 世界空間位置
float2 uv: TEXCOORD2; // 紋理坐標(biāo)
};
// 頂點著色器函數(shù)
v2f vert(appdata_base v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex); // 頂點位置變換到裁剪空間
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal); // 世界空間法線
o.worldNormal = worldNormal;
// 讓外部的屬性可以影響到uv
//o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
// 簡化uv計算函數(shù)
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
return o;
}
這個頂點函數(shù)的主要功能是將輸入的頂點數(shù)據(jù)從對象空間轉(zhuǎn)換到裁剪空間,并為后續(xù)的渲染過程提供必要的信息,包括裁剪空間中的頂點位置、世界空間中的法線、紋理坐標(biāo)以及頂點的世界空間位置。
- 片元著色器函數(shù)
// 片元著色器函數(shù)
fixed4 frag(v2f i): SV_Target {
// 獲取環(huán)境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
// 紋理采樣
fixed4 texColor = tex2D(_MainTex, i.uv);
// 如果紋理的alpha值小于閾值,則丟棄該片段
if (texColor.a - _Cutoff < 0) {
// 裁剪掉
discard;
}
// 漫反射
// 獲取光源方向
//fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
// 簡化獲取光源方向
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed3 diffuse = _LightColor0.rgb * texColor.rgb * _Diffuse.rgb * max(
0, dot(worldLightDir, i.worldNormal) * 0.5 + 0.5);
// 組合最終顏色
fixed3 color = diffuse + ambient;
return fixed4(color, 1); // 輸出顏色
}
這段代碼是片元著色器函數(shù),主要功能包括:
對主紋理進行采樣,獲取像素的顏色信息(漫反射成分)。
根據(jù)光照情況,計算漫反射的顏色。
對高光遮罩紋理進行采樣,獲取像素的高光遮罩值。
根據(jù)高光遮罩值、高光反射顏色和光照強度,計算高光反射的顏色。
將漫反射和高光反射的顏色疊加,得到每個像素的最終顏色,并將其輸出。
三、效果

四、總結(jié)
透明度測試(Alpha Test)是一種常用的渲染技術(shù),可以根據(jù)像素的 Alpha 值進行裁剪或過濾,以實現(xiàn)各種透明效果。在 Shader 中實現(xiàn)透明度測試可以通過在片元著色器中進行 Alpha 值的比較,并使用 discard 語句來丟棄不符合條件的像素來實現(xiàn)。透明度測試在游戲開發(fā)、圖形特效制作等領(lǐng)域具有廣泛的應(yīng)用。
透明度測試的原理是根據(jù)像素的 Alpha 值與預(yù)設(shè)的閾值進行比較,如果 Alpha 值小于閾值,則將該像素丟棄,不進行繪制,從而實現(xiàn)透明效果。這種技術(shù)常用于處理帶有透明度的紋理,例如樹葉、玻璃等材質(zhì),以及實現(xiàn)裁剪、遮擋等效果。
在 Shader 中實現(xiàn)透明度測試通常涉及以下步驟:
在片元著色器中獲取像素的紋理顏色以及 Alpha 值。
根據(jù)獲取的 Alpha 值與預(yù)設(shè)的閾值進行比較。
如果 Alpha 值小于閾值,則使用 discard 語句丟棄該像素,否則繼續(xù)進行后續(xù)的渲染計算。
根據(jù)渲染需求,可以選擇合適的閾值和處理邏輯,以達到期望的透明效果。
透明度測試在游戲開發(fā)中常用于優(yōu)化渲染性能,減少不可見部分的渲染開銷,同時也是實現(xiàn)復(fù)雜透明效果的重要手段之一。