Shader-透明效果-透明度混合

透明度混合相較于透明度測試更加復雜一些,透明度混合可以得到真正的半透明效果,使用當前片元和透明度作為混合因子,與已經存儲在顏色緩沖區的顏色值進行混合,得到新的顏色。透明度混合需要關閉深度寫入,這使得我們需要關注物體的渲染順序。
我們使用Unity的混合指令Blend,想實現半透明的效果就要把當前自身的顏色和已經存在的顏色緩沖中的顏色進行混合,混合時使用的函數就是該指令決定的。

ShaderLab Blend指令
Blend Off關閉混合
Blend SrcFactor DstFactor開啟混合,并設置混合因子。源顏色乘SrcFactor,目標顏色乘以DstFactor,再將兩者相加后存入顏色緩存中。

Blend.PNG

相較于透明度測試,代碼部分改變,Tags的Queue標簽設置為Transparent,RenderType標簽讓Shader歸入提前定義的組,我們通過ZWriteOff關閉深度寫入,Blend設置兩個混合因子。
在fragment中,我們返回的的Color值包括一個Alpha值。

Shader "Unlit/AlphaBlend"
{
    Properties{
        _Color("Main Tint",Color) = (1,1,1,1)
        _MainTex("Main Tex", 2D) = "white"{}
        _AlphaScale("Alpha Scale", Range(0,1)) = 1
    }
        SubShader{
            Tags{"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
            Pass{
                Tags{"LightMode" = "ForwardBase"}
                ZWrite Off
                Blend SrcAlpha OneMinusSrcAlpha

                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "Lighting.cginc"

                fixed4 _Color;
                sampler2D _MainTex;
                float4 _MainTex_ST;
                fixed _AlphaScale;

                struct a2v {
                    float4 vertex : POSITION;
                    fixed3 normal : NORMAL;
                    float4 texcoord : TEXCOORD0;
                };

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

                v2f vert(a2v v) {
                    v2f o;
                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.worldNormal = UnityObjectToWorldNormal(v.normal);
                    o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                    return o;
                }

                fixed4 frag(v2f i) :SV_Target{
                    fixed3 worldNormal = normalize(i.worldNormal);
                    fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
                    fixed4 texColor = tex2D(_MainTex, i.uv);
                    fixed3 albedo = texColor.rgb * _Color.rgb;
                    fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));
                    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT * albedo;
                    return fixed4(diffuse + ambient, texColor.a * _AlphaScale);
                }
                ENDCG
            }
        }
}
AplhaBlendTest.PNG

透明度混合的雙面渲染
Cull Back是默認的,背對攝像機的一面不會被渲染
Cull Front 是面向攝像機的不會渲染

Pass{
                Tags{"LightMode" = "ForwardBase"}
                Cull Front
Pass{
                Tags{"LightMode" = "ForwardBase"}
                Cull Back

我們改動代碼,先渲染背面,再渲染正面,可以得到下面的結果

AlphaBlendCull.PNG
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。