CocosCreator全局扫光

效果预览

按钮或物体上出现扫光效果可以体现改物品的珍贵性,比如我们在SSR卡片或者付费按钮上加一个扫光效果可以增加玩家付费的欲望,而这个效果要是美术去做的话,需要大量序列帧,而用shader可以轻松的定制出各种各样的效果。

核心思路

让2条斜率相同的斜线中间夹住的部分变亮,并让这两条线保持相同的速度进行位移。然后周期回归到原点重新扫一遍。

实现过程

本demo是基于ccc2.4.8开发的。

首先我们先画一条线出来,斜率的方程是: y=k*x+b

我们只需要让2个斜线中间的区域变亮一点就可以了。对于不等式方程就是y > kx + b1 和 y < kx + b2;设变亮强度为flowStrength,那核心算法如下:

void main() {
  ...
  
  if ((y > k * x + b1) && (y < k * x + b2)) {
    o.rgb *= flowStrength;
  }
  
  ...
  gl_FragColor = o.rgb;
}

其次,我们要让线动起来,cocos内置的cc-global.chunk中的cc_time参数记录着游戏运行时间.

那上述的b1和b2需要跟随cc_time的变化而变化。

我们设扫光速度为flowSpeed,单次扫光周期为flowCycle,两条斜线之间的距离是flowWidth,就有下面两个公式:

b1 = (cc_time.x * flowSpeed) % flowCycle; (%是求模)

b2 = b1 + flowWidth;

在glsl中取模有个api是 mod ,而cc_time是不能直接用的,需要从顶点着色器传到片段着色器来,具体操作可以看我前面的文章。

最后要做的就是将坐标映射进去,我们设斜率为flowK,将uv对应的x和y代进去就有如下代码:

float b1 = mod(v_time.x * flowSpeed, flowCycle);
float b2 = b1 + flowWidth;
if ((uv.y > flowK * uv.x + b1) && (uv.y < flowK * uv.x + b2)) {
  o.rgb *= flowStrength;
} 

到这里调好材质球的参数(斜率、周期、线宽、扫光速度)就能得到单张图的扫光效果啦!

运行效果:

改良一下

实际装载到项目中发现,同一个材质球,宽高比不一样的图跑扫光效果的斜率不一样,这是因为uv没有去乘宽高比的系数问题导致的。这个的解决方案可以参考上一篇文章《CocosCreator追光效果+多相机RenderTexture应用》中,在代码里将图片的宽高比传进去(没办法,uv只是0~1,没有宽高信息)。但实际开发会觉得应用很麻烦,不仅要挂材质球,还要获取宽高传进去,所以就在想啊,有没有办法做一个全局扫光,一道光扫过来,有需求的图片依次做个扫光效果?

答案肯定是有的。

首先,在顶点着色器中,顶点经过矩阵变换获得世界坐标的顶点,将其传到片段着色器中

在片段着色器中我们做如下测试:

o.rgba = vec4(v_pos.xyz, 1.0);

将一张铺满全屏的图片应用这个shader我们将得到如下效果:

x方向是红®,y方向是绿(g),2D不考虑z,看得出从左到右x是从-1到1的,从下到上y也是从-1到1的,在两者叠加的部分r+g就成了黄色(右上角),将坐标收缩到0~1试试?

o.rgba = vec4((v_pos.x + 1.0)*0.5, (v_pos.y + 1.0)*0.5, (v_pos.z + 1.0)*0.5, 1.0);

嗯,整个画面就类似uv一样,左下是原点,从0~1的渐变,对应将上面代码的uv改成v_pos得到如下代码

void main() {
...
    float tx = (v_pos.x + 1.0)*0.5;
    float ty = (v_pos.y + 1.0)*0.5;
    if ((ty > flowK * tx + b1) && (ty < flowK * tx + b2)) 
    {
      o.rgb *= flowStrength;
    }
...
}

运行效果如下:

我们得到了一个全屏的扫光,嗯,将这个材质球拖到各个小图片上面,再将背景图缩小做对比试试?

最终效果

最终代码

完整工程如下:

git@gitee.com:onion92/cocos2d-shader-effect.git

down下来后运行这个场景即可。

小结

今天的扫光就暂时告一段落了,期间也参考了一下异名大佬的扫光效果,2d的shader会暂停告一段落,后续几篇文章会为大家带来3d的一些效果。

有兴趣的同学可以关注一下我的公众号。你们的支持是我创作的动力!

image

感谢各位的观看,希望在渲染的道路上与君共勉,相互成长!

6赞

mark一下

太棒了, 学习了

战略mark

不错,不过我觉得直接后处理更好,毕竟一个一个的拖 effect 太麻烦了

后处理的话全屏跟着一起扫光,如果需求是场景里面特定的几个图片做扫光的话,这种还是方便一点吧

可以通过layer进行分组,就可以后处理了,不需要一个一个拖

为什么不做一个spine呢?

[quote=“tdvgxxzf, post:1, topic:135952”],而这个效果要是美术去做的话,需要大量序列帧,而用shader可以轻松的定制出各种各样的效果。
[/quote]

然后搓shader才能显出水平!