Cocos Creator Shader Effect 系列 - 5 - 马赛克/像素化特效

本章为大家带来马赛克/像素化特效。

马赛克和像素化特效有点类似,只不过程度不同,视乎格子的数量多少,可以认为是马赛克,也可以认为是像素化

2d-sprite-mosaic.gif

一、马赛克特效原理

马赛克的原理很简单,一句话形容就是 m x n 方块内取同一颜色 ,具体为两个步骤:

  1. 将纹理分成 m x n 个方块
  2. 方块内取同一个颜色

至此,本章完,你已经可以根据这个原理去实现效果了。

二、马赛克代码实现

将纹理分成 m x n 个方块 ,m 和 n 应该属于外部控制,因此我们将这两个属性设置为uniform变量,并定义如下:

uniform Mosaic {
  // X轴方块数量
  float xBlockCount;
  // Y轴方块数量
  float yBlockCount;
}

那么我们又如何实现方块内取同一个颜色呢?其中一种解决方案

  1. 计算顶点所在方块
  2. 取该方块内某一点,代表该方块的颜色

举个例子:

图中A点,B点,我们很明显知道它是落在方块 (1,0) 上,按照上面的操作,实际上,A,B两点采用的是方块(1,0) 的颜色,这里也可以变相理解为 A,B两点的坐标映射(或者叫投影)到格子(1,0) 的坐标

explain

抽象一下,实际的问题就变为:

我们怎么计算某个点的映射格子呢?这里,我们尝试分步计算

2.1 计算点在X轴上坐落的格子

首先,X轴上,每个格子的宽度可以这样子求解

float blockWidth = 1.0 / xBlockCount;

为了避免 xBlockCount 为 0 的问题,导致出现除以 0 的问题,我们可以这样子优化一下:

// 计算x轴格子宽度
float xCount;
if (xBlockCount <= 0.0) {
  xCount = 1.0;
} else {
  xCount = xBlockCount;
}
float blockWidth = 1.0 / xCount;

然后,用点的X坐标除以格子的宽度,然后向下取整,就可以得出点在X轴上哪个格子了

float blockXIndex = floor(v_uv0.x / blockWidth); 

2.2 计算点在Y轴上坐落的格子

同理,我们也可以求出点在Y轴上的哪个格子:

// 同理,求出当前 v_uv0 在y轴上的哪个格子
float yCount; 
if (yBlockCount <= 0.0) {
  yCount = 1.0;
} else {
  yCount = yBlockCount;
}
float blockHeight = 1.0 / yCount;
float blockYIndex = floor(v_uv0.y / blockHeight);

2.3 计算格子颜色

现在我们知道点是坐落格子是 (blockXIndex, blockYIndex) ,那么这个格子取什么颜色呢?

一般而言,我们取格子中心点所在颜色作为格子的颜色,当然你也可以有不同的实现。

计算格子中心点其实也很好算

// X:格子宽度 * 格子索引 + 半个格子的宽度
// Y:格子高度 * 格子索引 + 半个格子的高度
vec2 pos = vec2(blockWidth * blockXIndex + blockWidth * 0.5, blockHeight * blockYIndex + blockHeight * 0.5);

// 即
vec2 pos = vec2(blockWidth * (blockXIndex + 0.5), blockHeight * (blockYIndex + 0.5));

OK,现在我们可以得出了完整的映射代码

code

通过上面这份代码,我们就可以将顶点映射到不同格子,并且实现同一个格子显示同一个颜色(颜色为格子中心点的颜色)了。

2.4 应用映射

片段着色器 中应用一下映射刚刚的映射函数,更新每个 uv0 的实际映射坐标:

CCProgram fs

加上一些我们在 Cocos Creator Shader Effect 系列 - 3 - Effect 文件调试 中说到的调试手段,你就能得到马赛克的效果了

2d-sprite-mosaic.gif

三、总结

从上面的动图,你可以看到,视乎格子数量多少,一定程度上可以叫马赛克,在另外一个程度上,也可以叫像素化,重点在于 格子数量 这个变量,实际使用的时候,我们可以根据自己的需求去进行控制。

另外一个点就是,本张我们介绍了点映射或者叫 点投影 ,这是一个很好玩的操作,不同的投影方式能产生不同的效果,可以想点什么效果,去试试玩~

OK,本章完,完整代码在我的 Github 仓库Gitee 仓库 中可以找到。

下一篇:

上一篇:

推荐阅读更多精彩内容

  • 此刻,秋风乍起,片片落叶皆写满诗意,然我却终究提不起兴趣来写一首关于秋天的诗。 许是秋天并未真正携着清风到来的缘故...
    颜语蘅阅读 2,236评论 39 44
  • “格”是人格,“局”是胸怀。做人做事不仅要注重细节,更要具有胸怀。两者相得益彰...
    冰夫阅读 34评论 0 0
  • 面向对象:点餐的菜单是直接面对点菜,这是面向对象。 面向对象过程:后厨厨师做饭,如何做,先放什么后放什么。 *对象...
    if_mflz阅读 30评论 0 0