返回

高斯模糊

效果

原理

高斯模糊采用的是卷积计算,采用的卷积核为高斯核,高斯核是一个正方形大小的滤波核。其权重如图片左边所示。

当我们将左边的二位高斯核进行拆分可以得到右边的两个一维高斯核(计算X轴对象时将该对象列的所有数值相加,得到该对象在X轴上的一维高斯核值),通过对右边两个一维高斯核观察我们可以进一步简化得到三个权重值: 0.4026, 0.2442, 0.0545

源码

Shader "FoxShader/GaussianBlur"
{
    //-----------------------------------【属性 || Properties】------------------------------------------
    Properties
    {
        [PerRendererData] _MainTex ("Texture", 2D) = "white" { }
        _BlurSize ("Blur Size", Range(0, 20)) = 1.0
    }
    
    //-------------------------CG着色语言声明部分 || Begin CG Include Part----------------------
    CGINCLUDE
    sampler2D _MainTex;
    half4 _MainTex_TexelSize;//计算相邻像素的纹理坐标偏移量
    float _BlurSize;
    
    struct appdata
    {
        float4 vertex: POSITION;
        float2 uv: TEXCOORD0;
        float4 color: COLOR;//颜色
    };
    
    struct v2f
    {
        float2 uv[5]: TEXCOORD0;
        float4 pos: SV_POSITION;
        float4 color: COLOR;
    };
    //顶点着色器代码块Pass1
    v2f vertBlurVertical(appdata v)
    {
        v2f o;
        o.pos = UnityObjectToClipPos(v.vertex);
        o.color = v.color;
        
        //使用垂直方向纹素大小进行偏移
        half2 uv = v.uv;
        //原点
        o.uv[0] = uv;
        //上方一格
        o.uv[1] = uv + float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
        //下方一格
        o.uv[2] = uv - float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
        //上方两格
        o.uv[3] = uv + float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
        //下方两格
        o.uv[4] = uv - float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
        
        return o;
    }
    //顶点着色器代码块Pass2
    v2f vertBlurHorizontal(appdata v)
    {
        v2f o;
        o.pos = UnityObjectToClipPos(v.vertex);
        o.color = v.color;
        
        //使用垂直方向纹素大小进行偏移
        half2 uv = v.uv;
        //原点
        o.uv[0] = uv;
        //右方一格
        o.uv[1] = uv + float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;
        //左方一格
        o.uv[2] = uv - float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;
        //右方两格
        o.uv[3] = uv + float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;
        //左方两格
        o.uv[4] = uv - float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;
        
        return o;
    }
    //片元着色器代码块(共用)
    fixed4 fragBlur(v2f i): SV_Target
    {
        //高斯权重
        float weight[3] = {
            0.4026, 0.2442, 0.0545
        };
        
        //下面循环格子顺序:原点,右方一格,左方一格,右方两格,左方两格
        //滤波结果
        fixed4 sum = tex2D(_MainTex, i.uv[0]) * weight[0];
        
        for (int it = 1; it < 3; it ++)
        {
            sum += tex2D(_MainTex, i.uv[it * 2 - 1]) * weight[it];
            sum += tex2D(_MainTex, i.uv[it * 2]) * weight[it];
        }
        
        return sum;
    }
    ENDCG
    
    //-------------------结束CG着色语言声明部分  || End CG Programming Part-----------------
    
    
    //----------------------------------【子着色器 || SubShader】---------------------------------------
    SubShader
    {
        Tags { "RenderType" = "Transparent" "Queue" = "Transparent" "IgnoreProjector" = "True" "CanUseSpriteAtlas" = "True" "PreviewType" = "Plane" }
        ZWrite Off Blend  SrcAlpha OneMinusSrcAlpha Cull Off
        
        Pass
        {
            NAME "GAUSSIAN_BLUR_VERTICAL"
            
            CGPROGRAM
            
            #pragma vertex vertBlurVertical
            #pragma fragment fragBlur
            #pragma fragmentoption ARB_precision_hint_fastest
            
            #include "UnityCG.cginc"
            
            ENDCG
            
        }
        
        Pass
        {
            NAME "GAUSSIAN_BLUR_HORIZONTAL"
            
            CGPROGRAM
            
            #pragma vertex vertBlurHorizontal
            #pragma fragment fragBlur
            #pragma fragmentoption ARB_precision_hint_fastest
            
            #include "UnityCG.cginc"
            
            ENDCG
            
        }
    }
    Fallback off
}

Licensed under CC BY-NC-SA 4.0
0