theme: nico
包括:高性能 Wasm + WebGL 渲染引擎、Lottie 动画 WebGL 渲染、WebGL 帧差序列帧等。
前言
随着 Web 前端技术的不断发展,越来越多的新兴技术方案被引入到 Web 开发中,其中 Wasm 和 WebGL 作为前端领域的两大利器,为开发者带来了更多的可能性。
本文将结合2024 年抖音欢笑中国年的部分项目,重点介绍如何利用 Wasm 和 WebGL 对目前流行的一些前端互动技术(比如 Lottie、渲染引擎、动画图片等)进行创新和实践,利用 Wasm 和 WebGL 等新技术方案的特性和优势提升业务性能和流畅度,给用户带来更好的体验。
Simple 渲染引擎
WebAssembly(Wasm)是一种可以在 Web 浏览器中运行,提供比 JavaScript 更高的性能,并且支持多种编程语言的全新的字节码格式;基于其高性能的优势,我们团队尝试将其应用到渲染场景中,推出了基于 Wasm + WebGL 的高性能、轻量化的 Simple 渲染引擎。
以期借助于 Wasm 的高性能计算,以 Simple 引擎为基础,保持轻量化的同时,解决目前前端动效和轻互动场景主流技术方案如 Lottie 动画、动画图片(序列帧、Apng、WebP)、JS 渲染引擎等存在的能力受限、资源体积大、性能较低等问题。
引擎架构
考虑到前端用户学习和使用成本,Simple 引擎使用 TypeScript 语言开发上层接口,主要是利用 TS 封装简单对象,同时做类型提示方便前端用户使用,另外还提供尽可能高性能的方式和 Wasm 进行交互;底层则使用 C/C++,主要处理计算工作,比如:矩阵计算、图形计算、动画计算、动态合批等;
Simple 引擎目前的渲染管线主要以 2D 为主,也分为两部分:JS 部分负责处理数据量少但是 GL 调用频繁的操作,Wasm 部分则相反负责处理数据量多但是 GL 调用少的操作,尽可能达到性能最优解。
整体架构如下:
性能收益
受益于 Wasm 的计算性能优势,Simple 引擎相比主流的 JS 渲染引擎,比如: PixiJS 6.3、Cocos 2.4 在 Spine 动画、精灵旋转、精灵跳动、图形水平移动等基准性能测试场景中取得了不俗的表现:
以上测试数据来自 Android OPPO Find X1 抖音跨端框架 V8 环境,可以看到基于 Wasm 的 Simple 引擎相比基于 JS 的引擎性能提升明显,计算任务越复杂,性能收益越大。
计算任务复杂度:骨骼动画 > 图形计算 > 旋转变换 > 位移变换
测试代码
100 个 Spine 动画 Simple 和 Cocos 2.4 测试代码如下:
- Cocos 2.4
- Simple
兼容性
从 2015 年 Wasm 项目正式启动到现在,经过多年的发展 Wasm 规范不断完善和扩展,目前主流的浏览器已经全面支持 Wasm 技术;同时 Simple 引擎最早在 2022年7月启动,之后在直播、财经、头条、音乐、小说等多个业务场景中落地,并在 2024 年初获得了在春节项目中应用的机会。
从数据来看抖音跨端框架中使用 Wasm 的用户占比高达 96.97% ,对于不支持 Wasm 的情况也可以使用 Simple 引擎编译的 asm.js 版本来进行降级。
经过一年多的反复实践与验证,总得来说 Simple 引擎兼容性表现稳定可靠。
Lottie WebGL 渲染
Lottie WebGL 渲染是利用上文提到的 Wasm + WebGL 渲染引擎去渲染 Lottie 动画的方案,在几乎完美还原 Lottie 动画的基础上,利用引擎封装好的相关机制(事件、渲染对象)扩展 Lottie 动画的交互控制能力,丰富其特性支持,以及基于 Wasm + WebGL 渲染提升动画性能。
性能收益
Lottie 是动画 Airbnb 公司开源的跨平台动画框架,支持将 AE 中设计的动画导出为 Json 协议,是前端最流行的动画协议;但是在 Web 上官方只提供了三种渲染方式(SVG、Canvas 2D、HTML),并没有支持 WebGL:
而前端最流行的那些 JS WebGL 渲染引擎也没有直接支持 Lottie 动画,这就会带来三个问题:
官方渲染方案性能低
SVG、HTML 不适合处理大量元素的动画,而 Canvas 2D 的使用方式决定了它很难充分利用缓存机制,因此官方提供的这三种渲染方案其实性能是偏低的,会在较多、较复杂动画场景遭遇性能瓶颈。
如上图所示某 Lottie 动画在 Chrome 6 倍降速模拟移动端设备的性能表现,Lottie SVG 每帧耗时 5.77 毫秒,而 Simple Lottie 每帧耗时仅 1.10 毫秒,性能提升近 6 倍。
离屏 Canvas 渲染性能低
目前主流的 JS WebGL 渲染引擎只能使用离屏 Canvas 的方式去渲染 Lottie 动画,这种方式需要先创建一个离屏的 Canvas 然后用 Lottie 官方提供的 Canvas 2D 方式把动画的当前状态渲染到离屏 Canvas 中,接着再把这个离屏的 Canvas 用纹理的方式上传到 GPU,如果动画更新还需要重复这个流程。
相对复杂的渲染流程会导致其性能较低:
如上图所示,12 * 18 个 Lottie 动画在 i7 Mac Chrome 上测试,右侧 WebGL 直接渲染 Lottie 动画比左侧离屏 Canvas 渲染帧数高了 35 fps,性能提升近 3 倍。
JS 图形计算性能低
提升 Lottie 动画性能,除了要考虑渲染性能,还需要考虑计算性能,比如上面两个例子中的 Lottie 动画更多是图片元素,但是矢量图形也是 Lottie 动画中非常重要的功能。
如果基于目前主流的 JS WebGL 渲染引擎去渲染 Lottie 动画,在以矢量图形为主的 Lottie 动画中对比 Lottie 官方提供的 SVG 或者 Canvas 甚至会出现性能劣化的情况:
可以看到左侧 SVG 在动画峰值每帧仅需 6.26 毫秒,而右侧 PixiJS 在动画峰值每帧需要 11.68 毫秒。
基于 JS WebGL 渲染引擎渲染 Lottie 动画在矢量图形场景出现性能劣化最主要原因在于 SVG 的计算在浏览器封装的 Native 模块中进行,而 JS WebGL 渲染引擎的计算在 JS 中进行,哪怕是几乎优化到极致的 PixiJS 受限于 JS 也只能在图片元素等部分 Lottie 动画中取得性能优化收益;因此只有采用 Simple 引擎这种 Wasm + WebGL 的方案才能彻底、全面优化 Lottie 动画的性能:
相同场景 Simple Lottie 在动画峰值每帧仅需 5.35 毫秒(这其中还包含了 JS 动画参数插值计算部分,后续这部分 JS 计算也下沉 Wasm ,整体估计还能优化 1 毫秒 )。
交互控制
使用 Simple 引擎直接去渲染 Lottie 动画,除了性能上的收益之外,还利用引擎提供的能力增加了很多交互控制上的便利,比如:素材替换、事件监听、动画混合、文字变更、物理碰撞等等。
在 2024 年春节群红包雨项目中几乎全部的素材都是 Lottie 动画素材:
静态的 Lottie 素材结合 Simple Lottie 提供的动态交互能力就可以很方便的实现诸如红包点击、红包动态纹理、点中动画动态文字、大红包点击、连击动画动态数字等等。
举个例子,用户点中红包雨之后需要播放一个动画,整体是一个烟花的效果,需要随机展示不同的文字:
对于这个需求,设计同学只需要提供一个固定的 Lottie 动画,然后再提供一些其它的文字素材;开发则需要在代码中首先从动画中查找到文字精灵,然后随机选取一张文字纹理,最后更新文字精灵的纹理即可。
特性支持
使用 Simple 引擎去渲染 Lottie 动画,还能在原有 Lottie 特性支持的基础上增加更多的能力。比如从动画素材上来说我们可以把原始 Lottie 动画产物中零散的图片合成一张雪碧图,减少资源请求数量,减少纹理个数,提升渲染性能:
左侧是散图,右侧是雪碧图。除此之外甚至还能把图片转成压缩纹理,减少内存占用和加快渲染速度。
除了动画素材上的优化,还能给 Lottie 动画增加更多的渲染效果,比如:
粒子
滤镜
Simple 引擎通过 Shader 实现了很多常用的滤镜效果,比如:
左侧是模糊效果、右侧是颜色卷积效果。
自定义效果
基于 Simple 引擎提供的 WebGL 能力封装,还可以实现更多更丰富的自定义效果,比如:透明视频以及下面将要介绍 WebGL 帧差序列帧。
WebGL 帧差序列帧
帧差序列帧是一种基于 WebGL 1.0 标准的动画图片规范,由首帧图片、帧差图片(不透明帧差、半透明帧差)、帧差配置信息组成,一般包含 4 个文件:
背景
由于原始 Lottie 动画只支持少部分 AE 特性,对于不支持的特性设计师往往会把这些效果转成序列帧实现,这就会导致动画素材产物体积增加。而另一方面目前常用的视频、Apng、WebP 这些主流素材又各有各的问题,比如:
- 视频存在兼容性问题、不能交互、对低端机来说存在一定的性能压力;
- Apng、WebP 这些传统动画图片格式基本没怎么考虑帧间压缩:
上图是一张 Apng 解码后的信息,IDAT 表示首帧、fdAT 表示后续帧,可以看到后续帧和首帧几乎一样大,也就是说对于这个素材生成的 Apng 效果和简单拼接的原始序列帧差不多。
资源体积优化
基于上述现状,如果能基于兼容性最好的 WebGL 1.0 标准去实现一些类视频的简单自定义帧间压缩算法, 就能在动画场景以更小的资源体积完美替代序列帧、Apng、WebP。
对于一般素材帧差序列帧在体积上相比序列帧、Apng、WebP 会减少 50% 左右。
交互能力
帧差序列帧还能以更高的性能和提供任意时刻切任意帧的能力,实现一定的交互能力,从而满足一些轻互动场景的需求,对视频和 3D 模型形成差异化优势。
我们以小火人、打年兽和徽章项目为例:
- 小火人、年兽的动画状态是会随着用户的操作发生变化的,而视频是很难实现无缝的帧切换;
- 徽章需要 360 度旋转展示,同时还需要响应用户的滑动操作,一般情况下这里只能使用 3D 模型,那么整个项目就得以传统 3D 项目的流程去做,一方面成本会高出很多,另一方面考虑实时渲染性能压力,效果上可能还做不到百分百还原。而采用帧差序列帧的方案去做,项目成本就会低很多,同时效果上也不会有任何折扣。
未来展望
以上即是我们团队在 Wasm 和 WebGL 上的一些尝试与思考,虽然取得了一定的突破,但是方案本身还有很多需要优化和完善的地方:
- Wasm 标准依然在继续更新,SIMD、线程、垃圾回收、WASI 等新特性会进一步提升性能,同时可能会对现有引擎架构的升级产生很大影响;
- 帧差序列帧目前的帧间压缩效率只是优于序列帧、Apng、WebP,和视频相比还有很大差距;在保持现有优势的前提下怎么更接近视频是充满挑战的问题;
- Lottie 动画性能得到了优化,增加了很多能力;这些能力怎么高效率的开放给设计和开发去使用,怎么改进现有工作流效率,动效、轻互动的完美工作流需要满足哪些标准等等。
欢迎大家和我们团队一起探索和交流,共同推进技术的发展。
团队介绍
我们是抖音前端架构-互动体验技术团队,主要为字节跳动业务提供互动技术解决方案。技术产品包含面向互动 / 小游戏研发场景的 SAR Creator、高性能动效渲染引擎 Simple Engine、互动场景端能力套件 AnnieX 互动容器。
在这些技术建设与业务落地上,和抖音前端-互动创作团队、跨端框架团队、开放平台小游戏团队、用户增长-激励前端团队一同推进,不断探索字节跳动应用生态下的创新业务形态。
下期预告
下期主题是前端互动场景中的性能优化,将介绍前端互动页面在与宿主端共享有限进程资源的场景下遇到的性能问题及相应的解决方案,敬请期待。
往期回顾
2024 抖音欢笑中国年(二):AnnieX互动容器创新玩法解析
这是一个从 https://juejin.cn/post/7358083295241420850 下的原始话题分离的讨论话题