高斯模糊java代码_2D Shader学习——高斯模糊(三)

ef98301747e3a358fb0fc06c06190fae.png

0.前言

在学习高斯模糊前我们需要了解几个概念,这样才能帮助我们理解高斯模式是如何实现的。

  • 卷积
  • 卷积核

1.卷积

在介绍高斯模糊之前,我们需要了解一个概念叫做“卷积”。

它是用来实现高斯模糊的核心算法。

卷积大概是做什么事情的呢?

用大白话来说就是按比例合成自己和周围像素的颜色值。

计算过程大致如下

b22cdf0758277459d0f79ecfad2639d4.gif

由于卷积这个概念比较难解释(深度学习中也会用到卷积神经网络),暂且就不解释了,只要了解他是一种运算就行了。

2.卷积核

以上介绍了一种对图像处理的运算过程叫卷积,那卷积核是什么呢?

首先我们看一下如何按照卷积计算得到一个新的像素点

ce14afa6c91af56594d486b5ee689699.png

如图所示,我们把某一个像素的相邻像素和自身按照比例进行了混合,用新的值代替原像素。

在处理像素的过程中,中、上下左右的比例如图

9a03e942b6c3a152ae7a9246e0af9bb8.png

这种比例的集合,我们叫做卷积核

百度百科是这样定义的:

卷积核就是图像处理时,给定输入图像,输入图像中一个小区域中像素加权平均后成为输出图像中的每个对应像素,其中权值由一个函数定义,这个函数称为卷积核。

使用卷积核的代码一般都长这样

fixed4 color = tex2D (_MainTex, uv) * 0.5f;

color += tex2D(_MainTex,float2(uv.x - distance,uv.y)) * 0.125f;
color += tex2D(_MainTex,float2(uv.x + distance,uv.y)) * 0.125f;
color += tex2D(_MainTex,float2(uv.x,uv.y + distance)) * 0.125f;
color += tex2D(_MainTex,float2(uv.x,uv.y - distance)) * 0.125f;

3.高斯模糊

当我们知道了卷积和卷积核的概念后,实际上高斯模糊就是应用了一种特殊的卷积核,如图。

26300a9f47f41dd7817d19b35f6432e2.png

拿到了高斯模糊对应的卷积核后,Shader代码写起来就很容易了。

float _Blur;

fixed4 SampleSpriteTexture (float2 uv)
{
    // 1 / 16
    float offset = _Blur * 0.0625f;

    // 左上
    fixed4 color = tex2D (_MainTex, float2(uv.x - offset,uv.y - offset)) * 0.0947416f;
    // 上
    color += tex2D(_MainTex,float2(uv.x,uv.y - offset)) * 0.118318f;
    // 右上
    color += tex2D(_MainTex,float2(uv.x + offset,uv.y + offset)) * 0.0947416f;
    // 左
    color += tex2D(_MainTex,float2(uv.x - offset,uv.y)) * 0.118318f;
    // 中
    color += tex2D(_MainTex,float2(uv.x,uv.y)) * 0.147761f;
    // 右
    color += tex2D(_MainTex,float2(uv.x + offset,uv.y)) * 0.118318f;
    // 左下
    color += tex2D (_MainTex, float2(uv.x - offset,uv.y + offset)) * 0.0947416f;
    // 下
    color += tex2D(_MainTex,float2(uv.x,uv.y + offset)) * 0.118318f;
    // 右下
    color += tex2D(_MainTex,float2(uv.x + offset,uv.y - offset)) * 0.0947416f;


#if UNITY_TEXTURE_ALPHASPLIT_ALLOWED
    if (_AlphaSplitEnabled)
        color.a = tex2D (_AlphaTex, uv).r;
#endif //UNITY_TEXTURE_ALPHASPLIT_ALLOWED
    return color;
}

其实高斯模糊之所以叫高斯模糊,是因为他的卷积核的扩散过程符合正太分布,正态分布又名高斯分布。

e107d8318b968e0d687e6f6db3a85c19.png
正态分布图

所以只要满足正态分布的卷积核,我们就可以叫它高斯核。

4.完整代码

Shader "Starry/Sprite/GaussianBlur"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)

        // 模糊程度
        _Blur("Blur",Range(0,1)) = 0.01

        [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    }

    SubShader
    {
        Tags
        { 
            "Queue"="Transparent" 
            "IgnoreProjector"="True" 
            "RenderType"="Transparent" 
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

        Cull Off
        Lighting Off
        ZWrite Off
        Blend One OneMinusSrcAlpha

        Pass
        {
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile _ PIXELSNAP_ON
            #include "UnityCG.cginc"

            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                float2 texcoord  : TEXCOORD0;
            };

            fixed4 _Color;

            v2f vert(appdata_t IN)
            {
                v2f OUT;
                OUT.vertex = UnityObjectToClipPos(IN.vertex);
                OUT.texcoord = IN.texcoord;
                OUT.color = IN.color * _Color;
                #ifdef PIXELSNAP_ON
                OUT.vertex = UnityPixelSnap (OUT.vertex);
                #endif

                return OUT;
            }

            sampler2D _MainTex;
            sampler2D _AlphaTex;
            float _AlphaSplitEnabled;

            float _Blur;

            fixed4 SampleSpriteTexture (float2 uv)
            {
                // 1 / 16
                float offset = _Blur * 0.0625f;

                // 左上
                fixed4 color = tex2D (_MainTex, float2(uv.x - offset,uv.y - offset)) * 0.0947416f;
                // 上
                color += tex2D(_MainTex,float2(uv.x,uv.y - offset)) * 0.118318f;
                // 右上
                color += tex2D(_MainTex,float2(uv.x + offset,uv.y + offset)) * 0.0947416f;
                // 左
                color += tex2D(_MainTex,float2(uv.x - offset,uv.y)) * 0.118318f;
                // 中
                color += tex2D(_MainTex,float2(uv.x,uv.y)) * 0.147761f;
                // 右
                color += tex2D(_MainTex,float2(uv.x + offset,uv.y)) * 0.118318f;
                // 左下
                color += tex2D (_MainTex, float2(uv.x - offset,uv.y + offset)) * 0.0947416f;
                // 下
                color += tex2D(_MainTex,float2(uv.x,uv.y + offset)) * 0.118318f;
                // 右下
                color += tex2D(_MainTex,float2(uv.x + offset,uv.y - offset)) * 0.0947416f;


#if UNITY_TEXTURE_ALPHASPLIT_ALLOWED
                if (_AlphaSplitEnabled)
                    color.a = tex2D (_AlphaTex, uv).r;
#endif //UNITY_TEXTURE_ALPHASPLIT_ALLOWED

                return color;
            }

            fixed4 frag(v2f IN) : SV_Target
            {
                fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color;
                c.rgb *= c.a;
                return c;
            }
        ENDCG
        }
    }
}

效果如下

6bee6312a3fd5e809c6e0504d7a3614c.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值