返回
Featured image of post KawaseBlur与DualKawaseBlur

KawaseBlur与DualKawaseBlur

简介

KawaseBlur效果与高斯模糊相近,优化比高斯模糊更好,而DualKawaseBlur的性能优化比KawaseBlur更加强大

KawaseBlur算子图

DualKawaseBlur采用了下方两种Kawase进行合成达到的模糊效果

效果

模糊强度为20情况下三种残影形状(从左到右:高斯模糊,Kawase模糊,双重Kawase模糊),因为这里运用的是Sprite,所以只能看出他们残影不用,实际运用到屏后处理,效果差距都相互接近。

源码

Shader "FoxShader/KawaseBlur"
{
    Properties
    {
        //2D纹理
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" { }
        //模糊强度
        _BlurSize ("_BlurSize", Range(0, 20)) = 1.914
        //渐淡
        _SpriteFade ("SpriteFade", Range(0, 1)) = 1.0
    }
    
    SubShader
    {
        //渲染顺序=3000                     忽略投影                    渲染类型=半透明物体         预览类型=Plane          能否使用Sprite
        Tags { "Queue" = "Transparent" "IgnoreProjector" = "true" "RenderType" = "Transparent" "PreviewType" = "Plane" "CanUseSpriteAtlas" = "True" }
        //渲染设置
        //深度写入  混合类型=传统透明度混合             遮挡剔除
        ZWrite Off ZTest Always Blend SrcAlpha OneMinusSrcAlpha Cull Off
        
        Pass
        {
            
            CGPROGRAM
            
            //作为顶点着色器编译函数
            #pragma vertex vert
            //作为片元着色器编译函数
            #pragma fragment frag
            //使用低精度
            #pragma fragmentoption ARB_precision_hint_fastest
            #include "UnityCG.cginc"
            
            //顶点数据结构
            struct appdata_t
            {
                float4 vertex: POSITION;//顶点位置
                float4 color: COLOR;//颜色
                float2 texcoord: TEXCOORD0;//UV坐标
            };
            //片元数据结构
            struct v2f
            {
                float2 texcoord: TEXCOORD0;
                float4 vertex: SV_POSITION;//固定值——顶点位置
                float4 color: COLOR;
            };
            
            sampler2D _MainTex;
            float4 _MainTex_TexelSize;//计算相邻像素的纹理坐标偏移量
            float _SpriteFade;
            float _BlurSize;
            
            //顶点着色器代码块
            v2f vert(appdata_t IN)
            {
                v2f OUT;
                OUT.vertex = UnityObjectToClipPos(IN.vertex);//对象空间转裁剪空间
                OUT.texcoord = IN.texcoord;
                OUT.color = IN.color;
                return OUT;
            }
            
            
            //核心算法
            half4 KawaseBlur(sampler2D tex, float2 uv, float2 texelSize, half pixelOffset)
            {
                half4 o = 0;
                o += tex2D(tex, uv + float2(pixelOffset +0.5, pixelOffset +0.5) * texelSize);
                o += tex2D(tex, uv + float2(-pixelOffset -0.5, pixelOffset +0.5) * texelSize);
                o += tex2D(tex, uv + float2(-pixelOffset -0.5, -pixelOffset -0.5) * texelSize);
                o += tex2D(tex, uv + float2(pixelOffset +0.5, -pixelOffset -0.5) * texelSize);
                return o * 0.25;
            }
            
            //片元着色器代码块
            float4 frag(v2f i): COLOR
            {
                float4 _Blur_1 = KawaseBlur(_MainTex, i.texcoord.xy, _MainTex_TexelSize.xy, _BlurSize);
                //最终将结果
                float4 FinalResult = _Blur_1;
                FinalResult.rgb *= i.color.rgb;
                FinalResult.a = FinalResult.a * _SpriteFade * i.color.a;
                return FinalResult;
            }
            
            ENDCG
            
        }
    }
    Fallback "Sprites/Default"
}
Shader "FoxShader/DualKawaseBlur"
{
    //-----------------------------------【属性 || Properties】------------------------------------------
    Properties
    {
        [PerRendererData] _MainTex ("Texture", 2D) = "white" { }
        _BlurSize ("Blur Size", Range(0, 20)) = 2.0
    }
    
    //-------------------------CG着色语言声明部分 || Begin CG Include Part----------------------
    CGINCLUDE
    sampler2D _MainTex;
    float4 _MainTex_TexelSize;//计算相邻像素的纹理坐标偏移量
    half _BlurSize;
    
    struct appdata
    {
        float4 vertex: POSITION;
        float2 uv: TEXCOORD0;
    };
    
    struct v2f_DownSample
    {
        float4 vertex: SV_POSITION;
        float2 uv[5]: TEXCOORD0;
    };
    
    
    struct v2f_UpSample
    {
        float4 vertex: SV_POSITION;
        float2 uv[8]: TEXCOORD0;
    };
    
    //Pass1
    //顶点着色器代码块
    v2f_DownSample Vert_DownSample(appdata v)
    {
        v2f_DownSample o;
        o.vertex = UnityObjectToClipPos(v.vertex);
        
        half2 uv = v.uv;
        
        _MainTex_TexelSize *= 0.5;
        o.uv[0] = uv;
        
        o.uv[1] = uv - _MainTex_TexelSize * float2(1 + _BlurSize, 1 + _BlurSize);//top right
        o.uv[2] = uv + _MainTex_TexelSize * float2(1 + _BlurSize, 1 + _BlurSize);//bottom left
        o.uv[3] = uv - float2(_MainTex_TexelSize.x, -_MainTex_TexelSize.y) * float2(1 + _BlurSize, 1 + _BlurSize);//top left
        o.uv[4] = uv + float2(_MainTex_TexelSize.x, -_MainTex_TexelSize.y) * float2(1 + _BlurSize, 1 + _BlurSize);//bottom right
        
        // o.uv[1] = uv + float2(_BlurSize + 0.5, _BlurSize + 0.5) * _MainTex_TexelSize.xy;
        // o.uv[2] = uv + float2(-_BlurSize - 0.5, _BlurSize + 0.5) * _MainTex_TexelSize.xy;
        // o.uv[3] = uv + float2(-_BlurSize - 0.5, -_BlurSize - 0.5) * _MainTex_TexelSize.xy;
        // o.uv[4] = uv + float2(_BlurSize + 0.5, -_BlurSize - 0.5) * _MainTex_TexelSize.xy;
        
        return o;
    }
    //片元着色器代码块
    half4 Frag_DownSample(v2f_DownSample i): SV_Target
    {
        half4 sum = tex2D(_MainTex, i.uv[0]) * 4;
        for (int it = 1; it < 5; it ++)
        {
            sum += tex2D(_MainTex, i.uv[it]);
        }
        return sum * 0.125;
    }
    
    //Pass2
    //顶点着色器代码块
    v2f_UpSample Vert_UpSample(appdata v)
    {
        v2f_UpSample o;
        o.vertex = UnityObjectToClipPos(v.vertex);
        
        half2 uv = v.uv;
        
        _MainTex_TexelSize *= 0.5;
        _BlurSize = float2(1 + _BlurSize, 1 + _BlurSize);
        
        o.uv[0] = uv + float2(-_MainTex_TexelSize.x * 2, 0) * _BlurSize;
        o.uv[1] = uv + float2(-_MainTex_TexelSize.x, _MainTex_TexelSize.y) * _BlurSize;
        o.uv[2] = uv + float2(0, _MainTex_TexelSize.y * 2) * _BlurSize;
        o.uv[3] = uv + _MainTex_TexelSize * _BlurSize;
        o.uv[4] = uv + float2(_MainTex_TexelSize.x * 2, 0) * _BlurSize;
        o.uv[5] = uv + float2(_MainTex_TexelSize.x, -_MainTex_TexelSize.y) * _BlurSize;
        o.uv[6] = uv + float2(0, -_MainTex_TexelSize.y * 2) * _BlurSize;
        o.uv[7] = uv - _MainTex_TexelSize * _BlurSize;
        
        
        //偏移像素点
        // o.uv[0] = uv + _MainTex_TexelSize.xy * half2(-2, 0) * _BlurSize;
        // o.uv[1] = uv + _MainTex_TexelSize.xy * half2(-1, 1) * _BlurSize;
        // o.uv[2] = uv + _MainTex_TexelSize.xy * half2(0, 2) * _BlurSize;
        // o.uv[3] = uv + _MainTex_TexelSize.xy * _BlurSize;
        // o.uv[4] = uv + _MainTex_TexelSize.xy * half2(2, 0) * _BlurSize;//原UV坐标
        // o.uv[5] = uv + _MainTex_TexelSize.xy * half2(1, -1) * _BlurSize;
        // o.uv[6] = uv + _MainTex_TexelSize.xy * half2(0, -2) * _BlurSize;
        // o.uv[7] = uv - _MainTex_TexelSize.xy * _BlurSize;
        
        return o;
    }
    //片元着色器代码块
    half4 Frag_UpSample(v2f_UpSample i): SV_Target
    {
        half4 sum = 0;
        for (int it = 1; it < 5; it ++)
        {
            sum += tex2D(_MainTex, i.uv[it * 2 - 2]);
            sum += tex2D(_MainTex, i.uv[it * 2 - 1]) * 2;
        }
        return sum * 0.0833;
    }
    ENDCG
    
    //-------------------结束CG着色语言声明部分  || End CG Programming Part-----------------
    
    
    //----------------------------------【子着色器 || SubShader】---------------------------------------
    SubShader
    {
        Tags { "RenderType" = "Transparent" "Queue" = "Transparent" "IgnoreProjector" = "True" "CanUseSpriteAtlas" = "True" "PreviewType" = "Plane" }
        ZWrite Off ZTest Always Blend  SrcAlpha OneMinusSrcAlpha Cull Off

        Pass
        {
            NAME "GAUSSIAN_BLUR_VERTICAL"
            
            CGPROGRAM
            
            #pragma vertex Vert_DownSample
            #pragma fragment Frag_DownSample
            #pragma fragmentoption ARB_precision_hint_fastest
            
            #include "UnityCG.cginc"
            
            ENDCG
            
        }
        
        Pass
        {
            NAME "GAUSSIAN_BLUR_HORIZONTAL"
            
            CGPROGRAM
            
            #pragma vertex Vert_UpSample
            #pragma fragment Frag_UpSample
            #pragma fragmentoption ARB_precision_hint_fastest
            
            #include "UnityCG.cginc"
            
            ENDCG
            
        }
    }
    Fallback off
}
Licensed under CC BY-NC-SA 4.0
0