模糊算法

大部分模糊算法参考在这里

均值模糊

原理:通过卷积核对周围的像素进行平均,所有权重都是一样的

shader
1
2
3
// 这个是内置变量,x = 1/width, y = 1/height, z = width, w = height
// 这样x,y就能代表偏移值
float4 _MainTex_TexelSize;

2 * 2均值模糊,其他模糊以此类推

shader
1
2
3
4
5
6
7
8
// 2*2 均值模糊
half4 d = _MainTex_TexelSize.xyxy * half4(-1,-1,1,1) * _BlurOffset;
half4 s= 0;
s += tex2D(_MainTex, i.uv + d.zw);
s += tex2D(_MainTex, i.uv + d.zx);
s += tex2D(_MainTex, i.uv + d.xz);
s += tex2D(_MainTex, i.uv + d.xy);
s *= 0.25;

可通过在C#脚本中可以提高迭代次数

1
2
3
4
5
6
7
8
Graphics.Blit(source, rt1, material);

for(int i =0;i<_Interation;i++){
Graphics.Blit(rt1,rt2,material);
Graphics.Blit(rt2,rt1,material);
}

Graphics.Blit(rt1, destination, material);

高斯模糊

原理:同均值模糊,但是权重从中心往边缘呈高斯分布

优化后的高斯模糊 —> 直接使用55高斯核会很浪费,转换成两次1\5的操作,一次横向,一次纵向

因为已经有权重所以不用最后再除了

shader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 水平方向
half4 frag_HorizontalBlur (v2f_img i) : SV_Target{
half4 d = _BlurOffset.xyxy * half4(-1,-1,1,1);
half2 uv1 = i.uv + _BlurOffset*half2(1,0)*-2.0;
half2 uv2 = i.uv + _BlurOffset*half2(1,0)*-1.0;
half2 uv3 = i.uv;
half2 uv4 = i.uv + _BlurOffset*half2(1,0);
half2 uv5 = i.uv + _BlurOffset*half2(1,0)*2.0;

half4 s= 0;
s += tex2D(_MainTex, uv1) * 0.05;
s += tex2D(_MainTex, uv2) * 0.25;
s += tex2D(_MainTex, uv3) * 0.4;
s += tex2D(_MainTex, uv4) * 0.25;
s += tex2D(_MainTex, uv5) * 0.05;
return s;
}

双重模糊

先降采样,再升采样

shader层面不用修改

C#中在迭代过程中降低和增加图片大小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 降采样
for(int i =0;i<_Interation;i++){
// 水平方向
RenderTexture.ReleaseTemporary(rt2);
width /= 2;
height /= 2;
rt2 = RenderTexture.GetTemporary(width,height);
Graphics.Blit(rt1,rt2,material,0);

// 垂直方向
RenderTexture.ReleaseTemporary(rt1);
width /= 2;
height /= 2;
rt1 = RenderTexture.GetTemporary(width,height);
Graphics.Blit(rt2,rt1,material,1);
}
// 升采样
for(int i =0;i<_Interation;i++){
// 水平方向
RenderTexture.ReleaseTemporary(rt2);
width *= 2;
height *= 2;
rt2 = RenderTexture.GetTemporary(width,height);
Graphics.Blit(rt1,rt2,material,0);

// 垂直方向
RenderTexture.ReleaseTemporary(rt1);
width *= 2;
height *= 2;
rt1 = RenderTexture.GetTemporary(width,height);
Graphics.Blit(rt2,rt1,material,1);
}