大多数相册采用传统的跑马灯式轮播, 而通过使用Shader,我们可以为相册创建独特而富有动感的渐变过渡效果,使图片的切换变得更为流畅和自然。在游戏中,这可以用于两个场景间的过渡效果。
效果展示
直接用SD
生成了几张游戏背景图,由于mac的显卡不够给力,生成的图片高清度不够,勉强凑合着用。
实现思路
本实例的实现思路主要分为两个核心功能点:
- 图片的渐变:实现图片的平滑过渡。
- 图片的切换:保持图片在队列中循环切换。
图片渐变
图片的渐变是通过控制图片上每个像素点的透明度来实现的。这里采用了水平滚轴式的切换,这需要用到一个关于时间变化的垂直直线x = time。每个像素点的x坐标与此直线比较,左边的像素点透明度设为0,右边的透明度设为1。通过平滑取样的方法,就能够实现渐变过渡的效果:
javascript
void main () {
vec4 color = vec4(1, 1, 1, 1);
color *= texture(texture, v_uv0);
color *= v_color;
#if USE_TRAMSFORM
color.a = smoothstep(0.0, u_fade_radius, u_fade_radius + v_uv0.x - u_time);
#endif
gl_FragColor = color;
}
图片切换
对于图片的切换,所有的图片都在一个队列中。当渐变完成后,我们只需要将最上面的那张图片放到队列的最下面。这样,相册就能够持续循环播放。在此过程中,加入一些图片的状态处理,从而实现本文中所展示的渐变相册效果。
代码实现
下面是一段核心的代码实现,主要使用了Shader实现图片的渐变过渡,并通过定时器控制图片的切换:
javascript
isTransforming: boolean = false;
bgTramsform() {
if (this.isTransforming) return;
this.isTransforming = true;
let time = 0.0;
let node = this.switchNodeList[0];
let material = node.getComponent(cc.Sprite).getMaterial(0);
material.setProperty('u_fade_radius', this.fadeRadius);
material.setProperty('u_time', time);
material.define('USE_TRAMSFORM', true, 0, true);
let timer = setInterval(() => {
time += 0.06;
material.setProperty('u_time', time);
if (time > 1.0 + this.fadeRadius) {
this.switchNodeList.shift();
this.switchNodeList.push(node);
this.switchNodeList.forEach((node, idx) => node.zIndex = this.switchNodeList.length - idx)
material.define('USE_TRAMSFORM', false, 0, true);
this.isTransforming = false;
timer && clearInterval(timer);
}
}, 30);
}