技术美术百人计划 | 《3.2 混合与剔除》笔记

详见《Unity Shader入门精要》第八章

1. 混合

1.1. 定义

混合Blend 就是把两种颜色混在一起。具体就是把某一像素位置原来颜色和将要会上去的颜色,通过某种方式或者算法混在一起,从而实现新的效果。

例如:PS内的正片叠底,叠加都属于混合模式的一种。

ShaderLab 命令:Blend - Unity 手册

虽然所有图形 API 和硬件都支持混合功能,但对某些混合操作的支持较为有限。

启用混合会禁用 GPU 上的一些优化(主要是删除隐藏的表面/Early-Z),这些优化会增加 GPU 帧时间。

混合Blend 就是把两种颜色混在一起。具体就是把某一像素位置原来颜色和将要会上去的颜色,通过某种方式或者算法混在一起,从而实现新的效果。

例如:PS内的正片叠底,叠加都属于混合模式的一种。

ShaderLab 命令:Blend - Unity 手册

虽然所有图形 API 和硬件都支持混合功能,但对某些混合操作的支持较为有限。

启用混合会禁用 GPU 上的一些优化(主要是删除隐藏的表面/Early-Z),这些优化会增加 GPU 帧时间。

1.2. 类型

1.3. 混合等式

finalValue = sourceFactor * sourceValue operation destinationFactor * destinationValue

在这个等式中:

  • finalValue 是 GPU 写入目标缓冲区的值。
  • sourceFactor 在 Blend 命令中定义。
  • sourceValue 是片元着色器输出的值,也就是当前透明物体的颜色。
  • operation 是混合操作。
  • destinationFactor 在 Blend 命令中定义。
  • destinationValue 是目标缓冲区中现有的值,也就是透明物体后的背景颜色。

混合模式控制的就是源因子SrcFactor和目标因子DstFactor,在脚本里会看到的就是

Blend SrcFactor DstFactor

1.4. BlendOp 混合模式的操作符Operation

常见的:

指定 Blend 命令使用的混合操作。要使该命令生效,在同一个 Pass 代码块(如果该命令在 Pass 代码块中)或 SubShader 代码块(如果该命令在 SubShader 代码块中)中还必须有一个 BlendOp命令。

Shader "Examples/CommandExample"
{
    SubShader
    {
        // 。。。

        Pass
        {    
             // 为此通道启用减法混合
             Blend SrcAlpha One
             BlendOp Sub
            
            // 。。。
        }
    }
}

1.5. Unity对于混合自带的枚举

混合模式和深度开关:

举例:

1.6. 小结

常用混合命令及效果:

1.7. 实现方式

代码

1.

Shader "Custom/BlendMode"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Main Texture", 2D) = "white" {}

        [Enum(UnityEngine.Rendering.BlendOp)] _BlendOp("Blend Option",Float)=0
        [Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend("Source Blend",Float)=0
        [Enum(UnityEngine.Rendering.BlendMode)] _DstBlend("Destination Blend",Float)=0

        [Enum(Off,0,On,1)] _ZWriteMode("ZWrite Mode",Float)=1
    }
    SubShader
    {
        Tags{"RenderType"="Transparent""Queue"="Transparent"}
        ZWrite[_ZWriteMode]
        
        Blend [_SrcBlend][_DstBlend]
        BlendOp [_BlendOp]
       
       Pass 
       {
            CGPROGRAM

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

            fixed4 _Color;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _BlendOp;
            float _SrcBlend;
            float _DstBlend;
            float _ZWriteMode;

            struct a2v 
            {
                float4 vertex:POSITION;
                float2 uv:TEXCOORD0;
            };

            struct v2f 
            {
                float4 pos:SV_POSITION;
                float2 uv:TEXCOORD0;
            };

            v2f vert(a2v v)
            {
                v2f o;
                o.pos=UnityObjectToClipPos(v.vertex);
                o.uv=TRANSFORM_TEX(v.uv,_MainTex);
                return o;
            }

            fixed4 frag(v2f i):SV_Target 
            {
                
                return tex2D(_MainTex,i.uv)*_Color;
            }

            ENDCG
       }
    }
    FallBack "Diffuse"
}

2.

Shader "Custom/PSBlendMode"
{
    Properties
    {
        [IntRange] _ModeID("Mode ID",Range(0,26))=0

        _SrcColor("Color",Color)=(1,1,1,1)
        _DstColor("Color",Color)=(1,1,1,1)
       
        _SrcTex ("Source Texture", 2D) = "white" {}
        _DstTex ("Destination Texture", 2D) = "white" {}

        [HideInInspector] _IDChoose("",float)=0
    }
    SubShader
    {
        Tags{"RenderType"="Opaque""Queue"="Geometry"}
        ZWrite On       
        Blend Off       
       
       Pass 
       {
            CGPROGRAM

            #include "UnityCG.cginc"
            #include "PhotoshopBlendMode.cginc"
            #pragma vertex vert 
            #pragma fragment frag 

            fixed4 _SrcColor;
            fixed4 _DstColor;
            sampler2D _SrcTex;
            sampler2D _DstTex;
            float4 _SrcTex_ST;
            float4 _DstTex_ST;

            float _IDChoose;
            float _ModeID;           

            struct a2v 
            {
                float4 vertex:POSITION;
                float2 uv:TEXCOORD0;
            };

            struct v2f 
            {
                float4 pos:SV_POSITION;
                float2 uv:TEXCOORD0;
            };

            v2f vert(a2v v)
            {
                v2f o;
                o.pos=UnityObjectToClipPos(v.vertex);
                o.uv=TRANSFORM_TEX(v.uv,_DstTex);
                return o;
            }

            fixed4 frag(v2f i):SV_Target 
            {
                fixed4 Src=tex2D(_SrcTex,i.uv)*_SrcColor;
                fixed4 Dst=tex2D(_DstTex,i.uv)*_DstColor;
                return fixed4(OutPutMode(Src,Dst,_ModeID),1);
            }

            ENDCG
       }
    }
}

正常混合

变暗

正片叠底

滤色

2. 剔除

  1. 法线剔除也被称为背面消隐,根据法线朝向判断哪个面被剔除掉。可以用来控制是否双面渲染。

语法:Cull Off/ Front / Back

  1. 面裁剪clip函数会将参数小于0直接在片元着色器直接丢弃,常用于制作溶解,裁剪等效果

语法:clip();默认会切掉0的部分。

Shader "Custom/ClipMode"
{
    Properties
    {
        _CutOut("Cut Out",Range(0,1))=0.5
        _MainTex ("Main Texture", 2D) = "white" {}
      
        [Enum(UnityEngine.Rendering.CullMode)] _CullMode("Cull Mode",Float)=0
        
    }
    SubShader
    {
        Tags{"RenderType"="Transparent""Queue"="AlphaTest"}
        Cull [_CullMode]
        LOD 100
        
       
       Pass 
       {
            CGPROGRAM

            #include "UnityCG.cginc"
            #pragma multi_compile_fog

            #pragma vertex vert 
            #pragma fragment frag 
            
            float _CutOut;
            sampler2D _MainTex;
            float4 _MainTex_ST;           
            float _CullMode;

            struct a2v 
            {
                float4 vertex:POSITION;
                float2 uv:TEXCOORD0;
            };

            struct v2f 
            {
                float4 pos:SV_POSITION;
                float2 uv:TEXCOORD0;
                UNITY_FOG_COORDS(1)
            };

            v2f vert(a2v v)
            {
                v2f o;
                o.pos=UnityObjectToClipPos(v.vertex);
                o.uv=TRANSFORM_TEX(v.uv,_MainTex);
                return o;
            }

            fixed4 frag(v2f i):SV_Target 
            {
                fixed4 col=tex2D(_MainTex,i.uv);
                UNITY_APPLY_FOG(i.fogCoord,col);
                clip(col.a-_CutOut);

                return col;
            }

            ENDCG
       }
    }
    FallBack "Diffuse"
}

3. 作业

效果:

  • 14
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值