2019 年 11 月 11 日
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
}
}
}