Shader2_UI模糊效果(滤波)

前言

本章使用 滤波效果来介绍使用 .cginc。

模糊效果,其实模糊也可以称之为重影,一般的模糊是边线分的不太清,而用重影解释的话,就是由于出现多个边线叠在一起了。滤波是数学或者物理上的一个概念,总体可以理解成将波动较大的波变成相对平缓的波,如果清晰对应于边线明显、边线两边颜色值跳跃过大的话,模糊就对应于边线不清晰,颜色值过度平缓,所以使用滤波是可以达到这种效果的。这里先看一张模糊的效果图,可以发现模糊的比较厉害的时候就出现了很明显的多个影子。

滤波、模糊

filter 方法是一个支持 3x3 滤波矩阵的滤波方法,在上节课中,我们已经将该方法写到 .cginc 文件中了,只需要调用即可。

下面是关键部分代码。其实是针对每一个像素的颜色值,将其与周围八个像素的颜色值进行平均混合,如图,对于箭头所指向的像素点(请无视我的画工 ORZ)来说,就好比将中间的白色取 1/9,其余八个其他颜色的格子也各取1/9,然后加在一起,这就是滤波的原理,因为混合在了一起,所以颜色就会相对之前趋于平缓、模糊。

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
float _BlurOffset;

fixed4 ProcessColor(v2f IN)
{
float3x3 boxFilter =
{
1.0f/9, 1.0f/9, 1.0f/9,
1.0f/9, 1.0f/9, 1.0f/9,
1.0f/9, 1.0f/9, 1.0f/9,
};

return filter(boxFilter,_BlurOffset, _MainTex,IN.texcoord);
}


float4 filter(float3x3 filter, sampler2D tex, float2 coord, float2 texSize)
{
float4 outCol = float4(0,0,0,0);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
//计算采样点,得到当前像素附近的像素的坐标
float2 newCoord = float2(coord.x + (i-1)*_BlurOffset, coord.y + (j-1)*_BlurOffset);
float2 newUV = float2(newCoord.x / texSize.x, newCoord.y / texSize.y);
//采样并乘以滤波器权重,然后累加
outCol += tex2D(tex, newUV) * filter[i][j];
}
}
return outCol;
}

具体代码 使用.cginc

具体 shader 代码如下,其中有一句 #include “Assets/Shader/UIDefault.cginc”,就把上节课的 .cginc 拿了过来,就可以使用其中的代码了。

有些部分还是得写在具体 Shader 中,而不能放到 .cginc,比如 Properities,自定义的属性,一些标签等。

由于我们实现模糊效果,只需要对颜色值进行一些操作,所以只需要自定义 ProcessColor 方法,在其中调用 filter实现,其余部分调用 vertdefault 和 fragdefault 即可。

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
Shader "UI/Blur"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
_BlurOffset("Blur Offset", Range(0, 0.5)) = 0.05

_StencilComp ("Stencil Comparison", Float) = 8
_Stencil ("Stencil ID", Float) = 0
_StencilOp ("Stencil Operation", Float) = 0
_StencilWriteMask ("Stencil Write Mask", Float) = 255
_StencilReadMask ("Stencil Read Mask", Float) = 255

_ColorMask ("Color Mask", Float) = 15

[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
}

SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}

Stencil
{
Ref [_Stencil]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}

Cull Off
Lighting Off
ZWrite Off
ZTest [unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask [_ColorMask]

Pass
{
Name "Default"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0

#include "UnityCG.cginc"
#include "UnityUI.cginc"

#pragma multi_compile __ UNITY_UI_CLIP_RECT
#pragma multi_compile __ UNITY_UI_ALPHACLIP

#include "Assets/Shader/UIDefault.cginc"

float _BlurOffset;
fixed4 ProcessColor(v2f IN)
{
float3x3 boxFilter =
{
1.0f/9, 1.0f/9, 1.0f/9,
1.0f/9, 1.0f/9, 1.0f/9,
1.0f/9, 1.0f/9, 1.0f/9,
};

return filter(boxFilter,_BlurOffset, _MainTex,IN.texcoord);
}

v2f vert(appdata_t IN)
{
return vert_default(IN);
}

fixed4 frag(v2f IN) : SV_Target
{
return frag_default(IN);
}

ENDCG
}
}
}

滤波的其他用法

其实不光是 模糊效果,其余效果使用该方法也很可以实现,想一想和周围的像素进行比例取样,很多关于边界的效果都可以实现,主要针对的就是 矩阵里面的数值。大家可以改改数值试试能不能得到一些有趣的效果。

0%