Unity高斯模糊Shader

原理

这个shader姑且是根据自己的理解写的,如果有什么不对的评论区提醒一下咯,一般来说模糊和边缘检测这种效果是用卷积来实现的,可以通过使用不同的卷积核来获得图像的特征,模糊其实就是将计算的像素附近的像素乘上一定的权重加起来实现的效果,要保证这些权重的合为1,所以在计算出每个位置的权重后还要除以他们的平均值,用高斯函数的目的就是获得一个合理的权重,根据二维高斯函数的公式
可以把x^2 + y^2视为采样像素到中心像素的距离,所以代公式很容易可以得到二维高斯函数的值。

Shader "Hidden/Blurry"
{

	Properties
	{
		_MainTex("Base (RGB)", 2D) = "white" {}
		_Sigma("Sigma", Range(1.0, 5.0)) = 1.5
		_BlurRadius("BlurRadius", Range(1.0, 5.0)) = 3.0
	}
 
	CGINCLUDE
	#include "UnityCG.cginc"
	struct v2f_blur
	{
		float4 pos : SV_POSITION; //顶点位置
		float2 uv  : TEXCOORD0;	  //纹理坐标
	};
	

	//用到的变量
	sampler2D _MainTex;
	float4 _MainTex_TexelSize;
	//模糊半径
	float _BlurRadius;

	// σ
	float _Sigma;
	//vertex shader
	v2f_blur vert_blur(appdata_img v)
	{
		v2f_blur o;
		o.pos = UnityObjectToClipPos(v.vertex);
		o.uv = v.texcoord.xy;
		return o;
	}
 
	//fragment shader
	fixed4 frag_blur(v2f_blur i) : SV_Target
	{
		fixed4 color = fixed4(0,0,0,0);
 
		// 采样的9个像素点的偏移量
		float2 offsets[9] = 
		{	
			float2(-1, 1), float2(0, 1), float2(1, 1),
			float2(-1, 0), float2(0, 0), float2(1, 0),
			float2(-1, -1), float2(0, -1), float2(1, -1),
		};

		float pi = 3.1415;	// 圆周率
		float e = 2.7182;	// 数学常数

		float sum = 0;
		float weight[9];
		// 卷积
		for (int j = 0; j < 9; j++)
		{
			float l = length(_BlurRadius * _MainTex_TexelSize * offsets[j]);	// 求距离
			float g = (1.0 / (2.0 * pi * pow(_Sigma, 2.0))) * pow(e, (-(l * l) / (2.0 * pow(_Sigma, 2.0))));	// 高斯函数值
			weight[j] = g;
			sum += g;
		}

		for (int j = 0; j < 9; j++)
			weight[j] /= sum;

		for (int j = 0; j < 9; j++)
		{
			color += tex2D(_MainTex, i.uv + _BlurRadius * _MainTex_TexelSize * offsets[j]) * weight[j];
		}
		return color;
	}
 
	ENDCG

	SubShader
	{
		Pass
		{
			ZTest Always
			Cull Off
			ZWrite Off
			Fog{ Mode Off }
 
			CGPROGRAM
			#pragma vertex vert_blur
			#pragma fragment frag_blur
			ENDCG
		}
	}

}

将这个Shader作为后处理的Shader使用,可以得到效果:

Unity使用后处理相关的代码可以看这里

posted @ 2020-06-11 15:52  凌夜霜  阅读(1924)  评论(1编辑  收藏  举报