Unity Shader unity文档学习笔记(六):后处理之均值模糊(类似毛玻璃效果)

所谓模糊,也就是不清楚,清晰的图片,各个像素之间会有明显的过渡,而如果各个像素之间的差距不是很大,那么图像就会模糊了,极端一点的情况,当一张图片所有的像素之间颜色都差不多时,那么这张图片也就是一个纯色的图片了。模糊操作就是让像素间的颜色差距变小,比如A点是红色,A点周围的点是绿色,模糊就像用一把刷子,将A点和周围的点的颜色混合起来,变成最终的颜色。而怎样混合,按照不同的权值进行混合,就可以达到不同的效果了。比如均值模糊,以及著名的高斯模糊。

简单的模糊,直接用周围像素求和平均

shader

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Unlit/MySimpleBlurEffect"
{
	Properties{
		_MainTex("_MainTex",2D) = "white"{}
	}
     
	CGINCLUDE
    #include "UnityCG.cginc"
    struct v2f{
     float4 pos:SV_POSITION;
	 float2 uv:TEXCOORD0;
	 float2 uv1:TEXCOORD1;
	 float2 uv2:TEXCOORD2;
	 float2 uv3:TEXCOORD3;
	 float2 uv4:TEXCOORD4;
	};
	sampler2D _MainTex;
	float4 _MainTex_TexelSize;
	float _BlurRadius;

    v2f vert_blur (appdata_img i)
	{
		v2f v;
		v.pos = UnityObjectToClipPos(i.vertex);
		v.uv = i.texcoord.xy;
		v.uv1 = i.texcoord.xy +_BlurRadius*_MainTex_TexelSize*float2(1,1);
		v.uv2 = i.texcoord.xy +_BlurRadius*_MainTex_TexelSize*float2(1,-1);
		v.uv3 = i.texcoord.xy +_BlurRadius*_MainTex_TexelSize*float2(-1,1);
		v.uv4 = i.texcoord.xy +_BlurRadius*_MainTex_TexelSize*float2(-1,-1);
		return v;
	}
    fixed4 frag_blur(v2f v):SV_TARGET
	{
        fixed4 col = fixed4(0,0,0,0);
		col += tex2D(_MainTex,v.uv);
		col += tex2D(_MainTex,v.uv1);
		col += tex2D(_MainTex,v.uv2);
		col += tex2D(_MainTex,v.uv3);
		col += tex2D(_MainTex,v.uv4);
		return col*0.2;
	}
	ENDCG 
 
	//子着色器
	SubShader
	{
		//pass 0: blur effect
		Pass
		{
			ZTest Always
			Cull Off
			ZWrite Off
			Fog{ Mode Off }
 
			//直接调用vert_blur和frag_blur
			CGPROGRAM
			#pragma vertex vert_blur
			#pragma fragment frag_blur
			ENDCG
		}
	}

}

C#脚本 这个类挂在摄像机上


using UnityEngine;
using System.Collections;
 
//编辑状态下也运行
[ExecuteInEditMode]
//继承自PostEffectBase
public class BlurEffectBase : PostEffectBase
{
    //模糊半径
    public float BlurRadius = 3.0f;
 
    void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        if (_Material)
        {
 
            //blur 
            _Material.SetFloat("_BlurRadius", BlurRadius);
            Graphics.Blit(source, destination, _Material);
 
        }
    }
}

PostEffectBase基类

using System.Collections;
using UnityEngine;

//非运行时也触发效果
[ExecuteInEditMode]
//屏幕后处理特效一般都需要绑定在摄像机上
[RequireComponent(typeof(Camera))]
//提供一个后处理的基类,主要功能在于直接通过Inspector面板拖入shader,生成shader对应的材质
public class PostEffectBase : MonoBehaviour {
 
    //Inspector面板上直接拖入
    public Shader shader = null;
    private Material _material = null;
    public Material _Material
    {
        get
        {
            if (_material == null)
                _material = GenerateMaterial(shader);
            return _material;
        }
    }
 
    //根据shader创建用于屏幕特效的材质
    protected Material GenerateMaterial(Shader shader)
    {
        if (shader == null)
            return null;
        //需要判断shader是否支持
        if (shader.isSupported == false)
            return null;
        Material material = new Material(shader);
        material.hideFlags = HideFlags.DontSave;
        if (material)
            return material;
        return null;
    }
     
}


原图
在这里插入图片描述
后处理效果图
_BlurRadius =2
在这里插入图片描述
_BlurRadius =5
在这里插入图片描述
可以看到效果不是很好

改进

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class SimpleBlurEffect : PostEffectBase {
  
  public float BlurRadius = 1.0f;
  public int downSample = 2;
  public int iteration = 3;
  
    void OnRenderImage(RenderTexture source,RenderTexture destination)
    {
        if (_Material)
        {
            RenderTexture rt1 = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0, source.format);
            RenderTexture rt2 = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0, source.format);
            Graphics.Blit(source, rt1);

            for (int i = 0; i < iteration; i++)
            {
                _Material.SetFloat("_BlurRadius", BlurRadius);
                Graphics.Blit(rt1, rt2, _Material);
                Graphics.Blit(rt2, rt1, _Material);
            }
            Graphics.Blit(rt1, destination);
            RenderTexture.ReleaseTemporary(rt1);
            RenderTexture.ReleaseTemporary(rt2);
        }
    }
}

在这里插入图片描述
可以说效果非常好了
就是还有点耗性能
所以下篇学习高斯模糊

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值