Unity PostProcess Effect – 均值模糊

简介

这个博主说的特别好!推荐一波这个博客!原文链接

所谓模糊,也就是不清楚,清晰的图片,各个像素之间会有明显的过渡,而如果各个像素之间的差距不是很大,那么图像就会模糊了,极端一点的情况,当一张图片所有的像素之间颜色都差不多时,那么这张图片也就是一个纯色的图片了。模糊操作就是让像素间的颜色差距变小,比如A点是红色,A点周围的点是绿色,模糊就像用一把刷子,将A点和周围的点的颜色混合起来,变成最终的颜色。而怎样混合,按照不同的权值进行混合,就可以达到不同的效果了。比如均值模糊,以及著名的高斯模糊。
影响模糊程度的重要因素是模糊半径,模糊半径越大,模糊程度越大,模糊半径越小,模糊程度越小。那么,模糊半径是什么?所谓模糊半径,也就是我们采样的一个范围,比如我们模糊的半径很小,只是把像素和它周围的一圈定点混合,那么模糊的程度就很小,而如果我们加大模糊半径,极端情况是每个顶点都取了周围所有点,也就是整张图的像素平均值,那么这张图的颜色就会偏向一种颜色。

原理

顾名思义,均值模糊就是该像素的颜色值为自己和周围颜色值的均值。

实现

1.C#部分代码

using UnityEngine;

[ExecuteInEditMode]
public class NormalBlur : MonoBehaviour
{
    public Camera camera;
    public Shader shader;

    public float blurScale = 2;
    [Range(0,16)] public int iteration = 1;

    Material material = null;

    private Material GetMaterial()
    {
        if (material == null)
        {
            material = new Material(shader);
            material.hideFlags = HideFlags.HideAndDontSave;
        }
        return material;
    }

    void Start()
    {
        if(camera == null)
            camera = Camera.main;
        if(shader == null)
            shader = Shader.Find("FX/Blur");
    }

    void OnRenderImage(RenderTexture source, RenderTexture dest)
    {
        var mat = GetMaterial();
        mat.SetFloat("_BlurScale", blurScale);
        RenderTexture rt1 = RenderTexture.GetTemporary(source.width>>1,source.height>>1,0,source.format);
        RenderTexture rt2 = RenderTexture.GetTemporary(source.width>>1,source.height>>1,0,source.format);
        Graphics.Blit(source, rt1);

        for (int level = 0; level < iteration; level++)
        {
            rt2 = RenderTexture.GetTemporary(source.width>>level,source.height>>level,0,source.format); 
            Graphics.Blit(rt1, rt2, mat, 0);
            Graphics.Blit(rt2, rt1, mat, 0);
        }

        Graphics.Blit(rt1, dest);
        RenderTexture.ReleaseTemporary(rt1);
        RenderTexture.ReleaseTemporary(rt2);
    }
}

2.Shader部分

Shader "FX/Blur"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _BlurScale("Blur Scale", float) = 0.1
    }

    CGINCLUDE
        #include "UnityCG.cginc"

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

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

        sampler2D _MainTex;
        float4 _MainTex_TexelSize;
        float _BlurScale;

        v2f vert (appdata v)
        {
            v2f o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            o.uv = v.uv;
            return o;
        }

        fixed4 normalFrag (v2f i) : SV_Target
        {
            fixed4 color = tex2D(_MainTex, i.uv);
            color += tex2D(_MainTex, i.uv+float2(-1,0)*_BlurScale*_MainTex_TexelSize.x);
            color += tex2D(_MainTex, i.uv+float2(1,0)*_BlurScale*_MainTex_TexelSize.x);
            color += tex2D(_MainTex, i.uv+float2(0,1)*_BlurScale*_MainTex_TexelSize.y);
            color += tex2D(_MainTex, i.uv+float2(0,-1)*_BlurScale*_MainTex_TexelSize.y);
            return color/5;
        }
    ENDCG

    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            CGPROGRAM
                #pragma vertex vert
                #pragma fragment normalFrag
            ENDCG
        }
    }
}
效果预览


Done!(๑•̀ㅂ•́)و✧

Add a Comment

您的电子邮箱地址不会被公开。 必填项已用*标注