Unity shader中的透明混合

官方文档地址:https://docs.unity3d.com/cn/current/Manual/SL-Blend.html
openGL参考:https://learnopengl-cn.github.io/04 Advanced OpenGL/03 Blending/#_2
混合公式:finalValue = sourceFactor * sourceValue operation destinationFactor * destinationValue
翻译成中文就是 最终颜色(rgba) = 源混合系数 * 源混合颜色(rgba) +(-,*) 目标系数 * 目标颜色(rgba)

sourceFactor 在 Blend 命令中定义。
sourceValue 是片元着色器输出的值。
operation 是混合操作。
destinationFactor 在 Blend 命令中定义。
destinationValue 是目标缓冲区中现有的值。(就是屏幕上已经渲染出的其他物体的颜色)

混合系数就是0.5 1.0这种数值,在 Blend 命令中可以被定义.
常见混合语法

Blend SrcAlpha OneMinusSrcAlpha // 传统透明度
Blend One OneMinusSrcAlpha // 预乘透明度
Blend One One // 加法
Blend OneMinusDstColor One // 软加法
Blend DstColor Zero // 乘法
Blend DstColor SrcColor // 2x 乘法

Blend One One = shader片元输出的颜色 * 1 + 屏幕颜色 * 1
Blend SrcAlpha OneMinusSrcAlpha = shader片元输出的颜色 * 片元输出的color.a +屏幕颜色*(1-屏幕颜色.a)
也有其他写法

demo示例

写半透明效果记得关闭深度写入,改渲染队列
Tags { "Queue"="Transparent" "RenderType"="Transparent" "IgnoreProjector"="True" }
先看看Blend SrcAlpha OneMinusSrcAlpha
着色器代码

            fixed4 frag (v2f i) : SV_Target
            {
                //光照和环境光
                float3 worldLight = UnityWorldSpaceLightDir(i.worldPos.xyz);
                worldLight = normalize(worldLight);
                fixed NdotL = saturate(dot(i.worldNromal, worldLight));
                fixed4 color = tex2D(_MainTex, i.texcoord);
                color.rgb *= _MainColor.rgb * NdotL * _LightColor0;
                color.rgb += unity_AmbientSky;
                //令片元输出的alpha值 = _AlphaScale
                color.a *= _AlphaScale;

                return color;
            }

接着看看Blend One One

在这个模式下,自定义的蓝色变得很浅,而且我无论怎么调set alpha 它的透明度都不变

alpha测试

openGL里面用discord命令让我们想丢弃的颜色片段不被写入颜色缓冲区中

#version 330 core
out vec4 FragColor;

in vec2 TexCoords;

uniform sampler2D texture1;

void main()
{             
    vec4 texColor = texture(texture1, TexCoords);
    if(texColor.a < 0.1) //将小于阈值=0.1的片段手动丢弃掉
        discard;
    FragColor = texColor;
}

在unity shader中,用"Queue"="AlphaTest"和"RenderType=Transparent"进行alpha测试,将透明度小于阈值的片段丢弃掉
关了剔除会导致该PASS性能开销增大
示例:

Shader "Custom/alpha-test Transparent"
{
    Properties
    {
        _MainTex ("MainTex", 2D) = "white" {}
        _AlphaTest("AlphaTest", Range(0, 1)) = 0
        _Color("Main Color",COLOR)=(1,1,1,1)
    }
    SubShader
    {
         // 设置queue和RenderType
        Tags
        {
            "Queue" = "AlphaTest"
            "RenderType" = "TrannsparentCutout"
            "IgnoreProjector" = "True"
        }

        Pass
        {
            Tags{"LightMode" = "ForwardBase"}

            // 关闭几何体剔除
            Cull Off
            //为此子着色器启用 alpha-to-coverage 模式
            AlphaToMask On

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "UnityLightingCommon.cginc"

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

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed _AlphaTest;
            float4 _Color;

            v2f vert (appdata_base v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);

                float3 worldNormal = UnityObjectToWorldNormal(v.normal);
                o.worldNormal = normalize(worldNormal);

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float3 worldLight = UnityWorldSpaceLightDir(i.worldPos.xyz);
                worldLight = normalize(worldLight);
                fixed NdotL = saturate(dot(i.worldNormal, worldLight));
                fixed4 color = tex2D(_MainTex, i.texcoord);
               color.rgb *= NdotL * _LightColor0*_Color ;
 
                color.rgb += unity_AmbientSky;
               //clip(color.a - _AlphaTest);
                color.a = color.a<_AlphaTest?0:1;
                return color;
            }
            ENDCG
        }
    }
}

效果:

posted @ 2022-01-08 01:32  melt00  阅读(704)  评论(0编辑  收藏  举报