原理:通过把一个像素(其实也不是像素,是纹素,Texel)及其周围8个像素按照一定权重相加求得该像素最终的颜色。因此该纹素的最终颜色很大程度上取决于该纹素周围的纹素的颜色,从而达到模糊的效果。
1 取得周围纹素uv
_BlurSize为模糊程度,如果选取的周围8个纹素距离目标纹素很远,则模糊程度更大。
v2f vertBlurVertical(appdata_img v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
half2 uv = v.texcoord;
o.uv[0] = uv;
o.uv[1] = uv + float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
o.uv[2] = uv - float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
o.uv[3] = uv + float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
o.uv[4] = uv - float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
return o;
}
v2f vertBlurHorizontal(appdata_img v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
half2 uv = v.texcoord;
o.uv[0] = uv;
o.uv[1] = uv + float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;
o.uv[2] = uv - float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;
o.uv[3] = uv + float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;
o.uv[4] = uv - float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;
return o;
}
2 权重相加
fixed4 fragBlur(v2f i) : SV_Target {
float weight[3] = {
0.4026, 0.2442, 0.0545};
fixed3 sum = tex2D(_MainTex, i.uv[0]).rgb * weight[0];
for (int it = 1; it < 3; it++) {
sum += tex2D(_MainTex, i.uv[it*2-1]).rgb * weight[it];
sum += tex2D(_MainTex, i.uv[it*2]).rgb * weight[it];
}
return fixed4(sum, 1.0);
}
由于需要对横向的周围四个像素和纵向的周围四个像素分别按照权重相加,因此需要两个Pass做处理。当然可以放到一个Pass里面做。上面的v2f里面的uv[]长度是5个,如果放到一个Pass里面可以把长度拓展到9个,然后再vert()里面先求前5个横向,然后求纵向的5个。
因为分了两个Pass,所以对C#和Shader都会有影响。
1 Shader中因为两个Pass存在重复代码,因此使用CGINCLUDE、ENDCG来作为“头文件”,然后定义两个Pass中调用INCLUDE中的不同vert()函数就可以。
代码如下。
SubShader {
CGINCLUDE
#include "Un