高斯模糊可以实现模糊效果,可用于眩晕,场景动画等效果
高斯模糊利用了卷积计算,把每个像素和周围的像素混合
见代码实现
c#代码 ImageEffectBase
using UnityEngine;
namespace GameBase.Effect
{
[RequireComponent(typeof (Camera))]
[AddComponentMenu("")]
public class ImageEffectBase : MonoBehaviour
{
/// Provides a shader property that is set in the inspector
/// and a material instantiated from the shader
public Shader shader;
private Material m_Material;
protected virtual void Start()
{
// Disable if we don't support image effects
if (!SystemInfo.supportsImageEffects)
{
enabled = false;
return;
}
// Disable the image effect if the shader can't
// run on the users graphics card
if (!shader || !shader.isSupported)
enabled = false;
}
protected Material material
{
get
{
if (m_Material == null)
{
m_Material = new Material(shader);
m_Material.hideFlags = HideFlags.HideAndDontSave;
}
return m_Material;
}
}
protected virtual void OnDisable()
{
if (m_Material)
{
DestroyImmediate(m_Material);
}
}
}
}
c#代码 BlurEffect
using UnityEngine;
namespace GameBase.Effect
{
public class BlurEffect : ImageEffectBase
{
[Range(0, 10)]
[SerializeField]
private int _downSample = 1;//分辨率降低值
[SerializeField]
[Range(0, 8)]
private float _blurSize = 1;//取周围多远的像素
[SerializeField]
[Range(1, 10)]
private int _filterCount = 1;//滤波次数(越大性能越差)
private int ID_BlurSize;
private void OnEnable()
{
ID_BlurSize = Shader.PropertyToID("_BlurSize");
}
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if(_blurSize <= 0 )
{
Graphics.Blit(source, destination);
return;
}
int width = source.width >> _downSample;
int height = source.height >> _downSample;
if (width <= 0)
width = 1;
if (height <= 0)
height = 1;
if (_filterCount == 1)
{
RenderTexture bufferRT = RenderTexture.GetTemporary(width, height, 0, source.format);
if (material.HasProperty(ID_BlurSize))
{
material.SetFloat(ID_BlurSize, _blurSize);
}
Graphics.Blit(source, bufferRT, material, 0);
Graphics.Blit(bufferRT, destination, material, 1);
RenderTexture.ReleaseTemporary(bufferRT);
}
else
{
RenderTexture bufferRT1 = RenderTexture.GetTemporary(width, height, 0, source.format);
RenderTexture bufferRT2 = RenderTexture.GetTemporary(width, height, 0, source.format);
if (material.HasProperty(ID_BlurSize))
{
material.SetFloat(ID_BlurSize, _blurSize);
}
Graphics.Blit(source, bufferRT1, material, 0);
for (int i = 1; i < _filterCount; i++)
{
Graphics.Blit(bufferRT1, bufferRT2, material, 1);
Graphics.Blit(bufferRT2, bufferRT1, material, 0);
}
Graphics.Blit(bufferRT1, destination, material, 1);
RenderTexture.ReleaseTemporary(bufferRT1);
RenderTexture.ReleaseTemporary(bufferRT2);
}
}
}
}
shader代码
Shader "mgo/blur"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
_BlurSize("_BlurSize", range(0, 300)) = 1
}
SubShader
{
Tags{ "RenderType" = "Opaque" }
ZTest Off
cull Off
ZWrite Off
Pass
{
Name "Horizontal"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
float4 vertex:POSITION;
float2 uv:TEXCOORD0;
};
struct v2f
{
float4 pos:SV_POSITION;
float2 uv[5]:TEXCOORD0;
};
uniform sampler2D _MainTex;
//xxx_TexelSize 是用来访问xxx纹理对应的每个文素的大小 ,如一张512*512的图该值大小为1/512≈0.001953125
uniform float4 _MainTex_TexelSize;
uniform half _BlurSize;
v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
half2 uv = v.uv;
o.uv[0] = uv;
o.uv[1] = uv + _MainTex_TexelSize.xy * half2(_BlurSize, 0);
o.uv[2] = uv + _MainTex_TexelSize.xy * half2(-_BlurSize, 0);
o.uv[3] = uv + _MainTex_TexelSize.xy * half2(_BlurSize * 2, 0);
o.uv[4] = uv + _MainTex_TexelSize.xy * half2(-_BlurSize * 2, 0);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 col = 0.4 * tex2D(_MainTex,i.uv[0]);
col += 0.24 * tex2D(_MainTex, i.uv[1]);
col += 0.24 * tex2D(_MainTex, i.uv[2]);
col += 0.06 * tex2D(_MainTex, i.uv[3]);
col += 0.06 * tex2D(_MainTex, i.uv[4]);
return col;
}
ENDCG
}
Pass
{
Name "Vertical"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
float4 vertex:POSITION;
float2 uv:TEXCOORD0;
};
struct v2f
{
float4 pos:SV_POSITION;
float2 uv[5]:TEXCOORD0;
};
uniform sampler2D _MainTex;
uniform float4 _MainTex_TexelSize;
uniform half _BlurSize;
v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
half2 uv = v.uv;
o.uv[0] = uv;
o.uv[1] = uv + _MainTex_TexelSize.xy * half2(0, _BlurSize);
o.uv[2] = uv + _MainTex_TexelSize.xy * half2(0, -_BlurSize);
o.uv[3] = uv + _MainTex_TexelSize.xy * half2(0, _BlurSize * 2);
o.uv[4] = uv + _MainTex_TexelSize.xy * half2(0, -_BlurSize * 2);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 col = 0.4 * tex2D(_MainTex,i.uv[0]);
col += 0.24 * tex2D(_MainTex, i.uv[1]);
col += 0.24 * tex2D(_MainTex, i.uv[2]);
col += 0.06 * tex2D(_MainTex, i.uv[3]);
col += 0.06 * tex2D(_MainTex, i.uv[4]);
return col;
}
ENDCG
}
}
}