用shader做一个柿子颜色的过场动画
想要提高编写shader的水平,需要不断学习和练习。
跪着看完大神们的shadertoy作品后打算自己找个软柿子捏一捏。想了半天打算实现一下Nintendo Switch主机进eShop时的过场动画,仔细一看个过场的颜色和柿子还有点像,。本文将各个技术点整理分享给大家。
先来看一下原效果:
(eShop禁用主机录屏,视频为手机录制)
效果概括(可跳过)
原效果中有四种颜色轮流出现,并且互相覆盖,在视觉上有一种层次感。
在第一层播放过程中,第二层就已经出现,最多同时出现三种颜色。
四种颜色轮播完毕后动画暂停一小段时间,接着重新播放。第四种颜色和一开始的背景色相同,所以动画首尾连接。
入场的形状是阶梯造型,并且阶梯的距离在屏幕两边时比较窄,运行到屏幕中间时最大。
实现方案
运动轨迹
从原效果上看,运动时有缓入和缓出。
先简化处理,只控制某个颜色出场时第一个像素的 x 位置,选择 -cos(t) 作为运动的速度曲线。
对应地,将屏幕的x范围映射到(-1, 1)区间,x = 0的位置在屏幕中下方。
时间分片
控制某个颜色的动画是否显示的逻辑,采用“遮罩”的方式。原理和上一篇的“带通”类似。只不过这里的“遮罩”不是处理空间,而是处理时间。
可以理解为四个颜色的动画无时无刻都在自己运行,当时间处于某个区间内时,对应的颜色才会被画出来。
按顺序分配各颜色的出场时间,第一种颜色出场时间是0,第二种颜色是T1 = PI,第三种是T2 = 2PI,以此类推,第四种颜色播放完毕后是4PI。
实际运行时间不是4PI也没有关系,对全局时间 iTime 进行缩放可以很方便控制整体动画的节奏,所以4PI更像是一个逻辑时间单位。
阶梯造型
阶梯造型的规律性很强,可以看出是对y坐标做离散化拆成“行”,然后对各“行”进行一定的偏移。
// 对y离散化 float offsety = floor(uv.y * GRID_COUNT) / GRID_COUNT;// 时间t进行offsety偏移,为了避免在t = 0时出现负数导致三角函数“反弹”,做了clamp处理 mask = 1.0 - step(-cos(clamp(t - offsety, 0., TOTAL_TIME)), uv.x); col = mix(col, C1, mask);处理颜色交叉
本文一开始提到会有同屏出现三种颜色的情况。仔细观察效果可以发现在第一种颜色到达末端前第二种颜色已经出场了。要处理这种情况只需要对t进行偏移使下一个动画提前播放即可。
末尾动画停留
本来规划的4PI时间,但是由于上面将每个颜色的播放提前了,导致4PI长度的时间末尾会有一段空白时间,这段时间就刚好用来模拟原效果里的停留效果。想要调整停留时间可以修改 TOTAL_TIME 。
最后调整一下屏宽和动画速度,完工!
总结
老实说这柿子有点硬,我肝了一整天。
每个基本功能单独实现都很简单,但是合并到一起后经常出现牵一发动全身的情况。
写完shader再从头到尾看一遍,可以发现一些可以简化或者合并的部分。一开始我是采用 sin() 作为运动曲线,也尝试过映射到不同的屏幕坐标范围,后来都调整了。
目前的代码没有经过深度调优,尽量保持了和自己的思路比较匹配的写法。
完整代码可从下方领取。
Demo地址
shadertoy
https://www.shadertoy.com/view/ttfBDf
Cocos Creator
https://github.com/caogtaa/CCBatchingTricks
内含各种Cocos Creator编程技巧Demo
本文Demo可直接访问场景文件 SceneEnterEShop
技术交流,欢迎加我微信:ezglumes ,拉你入技术交流群。
推荐阅读:
音视频面试基础题
OpenGL ES 学习资源分享
一文读懂 YUV 的采样与格式
OpenGL 之 GPUImage 源码分析
推荐几个堪称教科书级别的 Android 音视频入门项目
觉得不错,点个在看呗~
总结
以上是生活随笔为你收集整理的用shader做一个柿子颜色的过场动画的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: OsWatcher 使用详解
- 下一篇: 图片实现水平垂直居中的方法