所谓模糊,也就是不清楚,清晰的图片,各个像素之间会有明显的过渡,而如果各个像素之间的差距不是很大,那么图像就会模糊了,极端一点的情况,当一张图片所有的像素之间颜色都差不多时,那么这张图片也就是一个纯色的图片了。模糊操作就是让像素间的颜色差距变小,比如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);
}
}
}
可以说效果非常好了
就是还有点耗性能
所以下篇学习高斯模糊