UnityShader:透明度測試(AlphaTest)

模板測試 發(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

image.png

二、使用步驟

  1. 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 
}

  1. SubShader 設(shè)置
SubShader
{
    Tags
    {
        "Queue" = "AlphaTest"  // 渲染隊列為AlphaTest
        "IgnoreProjector" = "True" // 忽略投影
    }
    
    LOD 100 // 細(xì)節(jié)級別
}

SubShader 定義了一組渲染設(shè)置,包括標(biāo)簽和細(xì)節(jié)級別。在這里,我們將渲染隊列標(biāo)簽設(shè)置為 “AlphaTest”,并且忽略投影

  1. 渲染 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。

  1. 定義結(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)以及頂點的世界空間位置。

  1. 片元著色器函數(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ù)高光遮罩值、高光反射顏色和光照強度,計算高光反射的顏色。
將漫反射和高光反射的顏色疊加,得到每個像素的最終顏色,并將其輸出。

三、效果

e4cbbfcb8862421caa405862dff57933.gif

四、總結(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ù)雜透明效果的重要手段之一。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容