透明度測試與透明度混合詳解《unity shader入門精要》學習筆記

透明度測試

       QUEUE標籤用於決定模型用於哪個渲染隊列(隊列索引號越小越先渲染越適合背景一類)

             名稱                 隊列索引號      描述
       Background    1000            適合背景物體

       Geometry      2000            不透明物體,默認的

            AlphaTest     2450            需要透明度測試的物體

       Transparent   3000            半透明物體,使用透明度混合的物體

       Overlay       4000            疊加特效,需要最後渲染的物體

 

    SubShader
    {
        //Queue標籤用於決定模型用於哪個渲染隊列(隊列索引號越小越先渲染越適合背景一類)

      Tags { "Queue"="AlphaTest" }

              pass{...}

}

Shader "LT/AlphaTest"
{
    Properties
    {
        _MainTex ("Texture"2D) = "white" {}
        _Color("Color",Color) = (1,1,1,1)
        _Cutoff("Cutoff",Range(0,1)) = 0.5
        
    }
    SubShader
    {
        //Queue標籤用於決定模型用於哪個渲染隊列(隊列索引號越小越先渲染越適合背景一類)
        Tags { "QUEUE"="AlphaTest" "IGNOREPROJECTOR"="True" "RenderType"="TransparentCutout" } //這一行千萬要注意空格,不然模型會出現一會兒部分透明一會兒不透明的問題

        Pass
        {
        Tags{"LightMode" = "ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _Color;
            fixed _Cutoff;
             
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal :NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 worldNormal :TEXCOORD1;
                float3 worldPos :TEXCOORD2;
            };

            //座標系轉換,模型空間->世界空間
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 worldNormal = normalize(i.worldNormal);
                fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
                fixed4 col = tex2D(_MainTex, i.uv);

                //alpha test
                clip(col.a - _Cutoff);
                //上面這句等同與下面這個
                //if((col.a - _Cutoff)<0.0)
//                {
//                    disscard;
//                }

                fixed3 albedo = col.rgb * _Color.rgb;
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
                fixed3 diffuse = _LightColor0.rgb * albedo * max(0,dot(worldNormal,worldLightDir));

                return fixed4(ambient + diffuse,1.0);
            }
            ENDCG
        }
    }
    FallBack "Transparent/Cutout/VertexLit"
}

Blend透明度混合

Blend 混合等式爲加法操作,默認情況

BlendOp BlendOperation混合操作命令

Untiy 官網有詳細說明:https://docs.unity3d.com/Manual/SL-Blend.html

我再根據閱讀《unity shader入門精要》後我的理解詳細說下具體的計算公式:

ShaderLab 中設置混合因子的命令

命令                      描述

Blend SrcFactor DstFactor   開啓混合,設置混合因子。Orgba= SrcFactor*Srgba + DstFactor*Drgba

 

Blend SrcFactor DstFactor,     開啓混合,設置混合因子,但是透明通道使用了不同的混合因子,公式如下:

SrcFactorA  DstFactorA          Orgb= SrcFactor*Srgb + DstFactor*Drgb,Alpha通道部分SrcFactorADstFactorA 公式: 

 Oa= SrcFactorA*Sa        +  DstFactorA*Da

公式中的變量:

Srgba:源顏色(該片元產生的顏色),可以理解爲:當前物體的顏色

Drgba:目標顏色(已存在於顏色緩存的顏色),可以暫時理解爲:先寫入顏色緩衝區的顏色

SrcFactor:源顏色的混合因子

DstFactor :目標顏色的混合因子

 

Blend factors

All following properties are valid for both SrcFactor & DstFactor in theBlend command.Source refers to the calculated color,Destination is the color already on the screen. The blend factors are ignored ifBlendOp is using logical operations.

One

因子爲1The value of one - use this to let either the source or the destination color come through fully.

Zero

因子爲0The value zero - use this to remove either the source or the destination values.

SrcColor

源顏色值,The value of this stage is multiplied by the source color value.

SrcAlpha

源顏色的透明通道(A通道)值The value of this stage is multiplied by the source alpha value.

DstColor

目標顏色值The value of this stage is multiplied by frame buffer source color value.

DstAlpha

目標顏色的透明通道(A通道)值The value of this stage is multiplied by frame buffer source alpha value.

OneMinusSrcColor

1-源顏色值The value of this stage is multiplied by (1 - source color).

OneMinusSrcAlpha

1-源顏色的透明通道(A通道)值The value of this stage is multiplied by (1 - source alpha).

OneMinusDstColor

1-目標顏色值The value of this stage is multiplied by (1 - destination color).

OneMinusDstAlpha

1-目標顏色的透明通道(A通道)值The value of this stage is multiplied by (1 - destination alpha).

Blend SrcFactor DstFactor, SrcFactorA  DstFactorA可以使用不同參數混合透明通道,例如我們想要混合後輸出顏色的透明度值就是源顏色的透明度。

Blend SrcAlpha OneMinusSrcAlpha , One Zero

Blend operations混合操作

The following blend operations can be used:

Add

Add source and destination together.

源顏色+目標顏色

Orgb = SrcFactor*Srgb + DstFactor*Drgb

Oa = SrcFactorA*Sa + DstFactorA*Da

Sub

Subtract destination from source.

源顏色-目標顏色

Orgb = SrcFactor*Srgb - DstFactor*Drgb

Oa = SrcFactorA*Sa - DstFactorA*Da

RevSub

Subtract source from destination.

目標顏色-源顏色

Orgb = DstFactor*Drgb - SrcFactor*Srgb

Oa = DstFactorA*Da - SrcFactorA*Sa

Min

Use the smaller of source and destination.

取源顏色和目標顏色最小值(與混合因子無關)

Orgba =(min(Sr,Cr), min(Sg,Cg), min(Sb,Cb), min(Sa,Ca))

Max

Use the larger of source and destination.

取源顏色和目標顏色最大值(與混合因子無關)

Orgba =(max(Sr,Cr), max (Sg,Cg), max (Sb,Cb), max (Sa,Ca))

LogicalClear

Logical operation: Clear (0)DX11.1 only.

DX11.1 only(只支持DX11

LogicalSet

Logical operation: Set (1)DX11.1 only.

LogicalCopy

Logical operation: Copy (s)DX11.1 only.

LogicalCopyInverted

Logical operation: Copy inverted (!s)DX11.1 only.

LogicalNoop

Logical operation: Noop (d)DX11.1 only.

LogicalInvert

Logical operation: Invert (!d)DX11.1 only.

LogicalAnd

Logical operation: And (s & d)DX11.1 only.

LogicalNand

Logical operation: Nand !(s & d)DX11.1 only.

LogicalOr

Logical operation: Or (s | d)DX11.1 only.

LogicalNor

Logical operation: Nor !(s | d)DX11.1 only.

LogicalXor

Logical operation: Xor (s ^ d)DX11.1 only.

LogicalEquiv

Logical operation: Equivalence !(s ^ d)DX11.1 only.

LogicalAndReverse

Logical operation: Reverse And (s & !d)DX11.1 only.

LogicalAndInverted

Logical operation: Inverted And (!s & d)DX11.1 only.

LogicalOrReverse

Logical operation: Reverse Or (s | !d)DX11.1 only.

LogicalOrInverted

Logical operation: Inverted Or (!s | d)DX11.1 only.

 

//正常混合,透明度混合

Blend SrcAlpha OneMinusSrcAlpha

 

//柔和相加

Blend OneMinusSrcAlpha

 

//正片疊底,源顏色和目標顏色相乘

Blend DstColor Zero

 

//兩倍相乘

Blend DstColor SrcColor

 

 

//變暗取當前顏色最小值,後面這句Blend One One不會對結果產生影響

BlendOp Min

Blend One One    // Blend Zero Zero效果也是一樣的

 

//變亮

BlendOp Max

Blend One One

 

//濾色

 

Blend OneMinusDstColor One //等同於

Blend  One OneMinusSrcColor

//線性減淡

Blend One One

 

shader 實例

Shader "LT/AlphaBlend"
{
    Properties
    {
        _MainTex ("Texture"2D) = "white" {}
        _Color("Color",Color) = (1,1,1,1)
        _AlphaScale("Alpha Scale",Range(0,1)) = 1
        
    }
    SubShader
    {
        Tags { "QUEUE"="Transparent" "IGNOREPROJECTOR"="True" "RenderType"="Transparent" }//這一行千萬要注意空格,不然模型會出現一會兒部分透明一會兒不透明的問題
           
        Pass
        {

            Tags{"LightMode" = "ForwardBase"}
            ZWrite off   //如果不關閉深度寫入,半透明物體離相機更近的話,進行深度測試後會將其後的物體表面剔除。導致沒有半透效果了,因此關閉深度寫入。
            
            Blend SrcAlpha OneMinusSrcAlpha     //透明度混合

//            Blend OneMinusDstColor One     //柔和相加

//            Blend DstColor Zero       //正片疊底,目標顏色*源顏色

//            BlendOp Min            //取顏色最小值
//            Blend Zero Zero     

//            BlendOp Max        ////取顏色最大值
//            Blend One One 

//            Blend OneMinusDstColor One  //濾色,與下面這句等價
//            Blend  One OneMinusSrcColor

     
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _Color;
            fixed _AlphaScale;
             
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal :NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 worldNormal :TEXCOORD1;
                float3 worldPos :TEXCOORD2;
            };

            //座標系轉換,模型空間->世界空間
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 worldNormal = normalize(i.worldNormal);
                fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
                fixed4 col = tex2D(_MainTex, i.uv);

                //alpha test
//                clip(col.a - _Cutoff);
                //上面這句等同與下面這個
                //if((col.a - _Cutoff)<0.0)
//                {
//                    disscard;
//                }
                fixed3 albedo = col.rgb * _Color.rgb;
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
                fixed3 diffuse = _LightColor0.rgb * albedo * max(0,dot(worldNormal,worldLightDir));

                return fixed4(ambient + diffuse,col.a * _AlphaScale);
            }
            ENDCG
        }
    }
    FallBack "Transparent/VertexLit"
}

 測試結果對比:

 

發佈了39 篇原創文章 · 獲贊 13 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章