马赛克是一种常用的图像处理手段,因为这种模糊效果看上去有一个个的小格子组,便形象的称这种画面为马赛克。当画面上的马赛克格子小到一定程度的时候,画面呈现出来的风格也叫像素风
demo
实现思路
核心思路就是把图片划分成M * N
个小格子,格子内取同一个颜色。我们前面经常用到texture(texture, v_uv0)
这个函数,它的作用就是把纹理贴图按uv进行取样,输出一个vec4
类型的颜色值,在实现马赛克效果的时候我们改为按M * N
个点来取样,也就是要找出每个格子的中心点,然后传入texture
函数,这样一来问题就变成了,如何计算每个格子的中心点。
从水平方向说起,每个格子的x轴中心坐标等于当前格子的x轴位置加上格子宽度的一半。格子数量x_count
通过外部传入,每个格子的宽为block_w = 1.0 / x_count
,每个格子的x轴位置等于当前格子的序号乘上格子的宽度,格子的序号为block_x_idx = floor(v_uv0.x / block_w)
,当前格子的位置为block_x_idx * block_w
,当前格子的中心点位置为block_w * (block_x_idx 0.5)
。同理可以得到格子中心点的垂直方向的位置:
vec2 getUvMapPos() {
float block_w = 1.0 / x_count;
float block_x_idx = floor(v_uv0.x / block_w);
float block_h = 1.0 / y_count;
float block_y_idx = floor(v_uv0.y / block_h);
return vec2(block_w * (block_x_idx 0.5), block_h * (block_y_idx 0.5));
}
有了映射的坐标,我们就可以直接进行颜色取样和赋值,为了便于控制,我们还可以加上一个宏开关:
代码语言:javascript复制void main () {
vec4 o = vec4(1, 1, 1, 1);
vec2 realPos = v_uv0;
#if USE_MASAIC
realPos = getUvMapPos();
#endif
o *= texture(texture, realPos);
o *= v_color;
gl_FragColor = o;
}
后面可以通过更改传进来的垂直和水平方向的格子数量来控制马赛克的大小,效果如下:
demo