透明度测试与透明度混合详解《unity shader入门精要》学习笔记

来源:互联网 发布:sql server 2008 sa 编辑:程序博客网 时间:2024/06/06 03:26

透明度测试

       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

O= SrcFactorA*Sa + DstFactorA*Da

Sub

Subtract destination from source.

源颜色-目标颜色

Orgb = SrcFactor*Srgb - DstFactor*Drgb

O= SrcFactorA*Sa - DstFactorA*Da

RevSub

Subtract source from destination.

目标颜色-源颜色

Orgb = DstFactor*Drgb - SrcFactor*Srgb

O= 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"
}

 测试结果对比:

 


阅读全文
0 1