2024 抖音欢笑中国年(五):Wasm、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 调用少的操作,尽可能达到性能最优解。

整体架构如下:

0b7490e96201ec48415abe448e6f41a3.png

性能收益

受益于 Wasm 的计算性能优势,Simple 引擎相比主流的 JS 渲染引擎,比如:PixiJS 6.3、Cocos 2.4 在 Spine 动画、精灵旋转、精灵跳动、图形水平移动等基准性能测试场景中取得了不俗的表现:

41134740c43c0f8270a2ceab7ee62943.jpeg

以上测试数据来自 Android OPPO Find X1 抖音 跨端框架 V8 环境,可以看到基于 Wasm 的 Simple 引擎相比基于 JS 的引擎性能提升明显,计算任务越复杂,性能收益越大

计算任务复杂度:骨骼动画 > 图形计算 > 旋转变换 > 位移变换

测试代码

100 个 Spine 动画 Simple 和 Cocos 2.4 测试代码如下:

  • Cocos 2.4

875be47a74bc90af5cb69348e23a163c.png
  • Simple

948015216feb3cc8f58f77b0b5edb2eb.png

兼容性

从 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:

2bdb4f1052a0931cbec0a992a4c85600.jpeg

而前端最流行的那些 JS WebGL 渲染引擎也没有直接支持 Lottie 动画,这就会带来三个问题:

官方渲染方案性能低

SVG、HTML 不适合处理大量元素的动画,而 Canvas 2D 的使用方式决定了它很难充分利用缓存机制,因此官方提供的这三种渲染方案其实性能是偏低的,会在较多、较复杂动画场景遭遇性能瓶颈。

0f212bf8c21d1df5ac9abe326db87ee2.jpegcb5db40736d2d31bf205c7617dad93a6.png

如上图所示某 Lottie 动画在 Chrome 6 倍降速模拟移动端设备的性能表现,Lottie SVG 每帧耗时 5.77 毫秒,而 Simple Lottie 每帧耗时仅 1.10 毫秒,性能提升近 6 倍。

离屏 Canvas 渲染性能低

目前主流的 JS WebGL 渲染引擎只能使用离屏 Canvas 的方式去渲染 Lottie 动画,这种方式需要先创建一个离屏的 Canvas 然后用 Lottie 官方提供的 Canvas 2D 方式把动画的当前状态渲染到离屏 Canvas 中,接着再把这个离屏的 Canvas 用纹理的方式上传到 GPU,如果动画更新还需要重复这个流程。

相对复杂的渲染流程会导致其性能较低:

bfc872288ec0fecc293985c55391846d.png

1b88f7c5e69fb147c2f2931f9e7681dd.png

如上图所示,12 * 18 个 Lottie 动画在 i7 Mac Chrome 上测试,右侧 WebGL 直接渲染 Lottie 动画比左侧离屏 Canvas 渲染帧数高了 35 fps,性能提升近 3 倍。

JS 图形计算性能低

提升 Lottie 动画性能,除了要考虑渲染性能,还需要考虑计算性能,比如上面两个例子中的 Lottie 动画更多是图片元素,但是矢量图形也是 Lottie 动画中非常重要的功能。

如果基于目前主流的 JS WebGL 渲染引擎去渲染 Lottie 动画,在以矢量图形为主的 Lottie 动画中对比 Lottie 官方提供的 SVG 或者 Canvas 甚至会出现性能劣化的情况:

d934ff9f49eab98c6e3a59b8d419940b.jpegc6801d39ecbae9a9050184ca80628455.jpeg

可以看到左侧 SVG 在动画峰值每帧仅需 6.26 毫秒,而右侧 PixiJS 在动画峰值每帧需要 11.68 毫秒。

基于 JS WebGL 渲染引擎渲染 Lottie 动画在矢量图形场景出现性能劣化最主要原因在于 SVG 的计算在浏览器封装的 Native 模块中进行,而 JS WebGL 渲染引擎的计算在 JS 中进行,哪怕是几乎优化到极致的 PixiJS 受限于 JS 也只能在图片元素等部分 Lottie 动画中取得性能优化收益;因此只有采用 Simple 引擎这种 Wasm + WebGL 的方案才能彻底、全面优化 Lottie 动画的性能

905f5c96220564096eae1925f85e8ce6.png

相同场景 Simple Lottie 在动画峰值每帧仅需 5.35 毫秒(这其中还包含了 JS 动画参数插值计算部分,后续这部分 JS 计算也下沉 Wasm ,整体估计还能优化 1 毫秒 )。

交互控制

使用 Simple 引擎直接去渲染 Lottie 动画,除了性能上的收益之外,还利用引擎提供的能力增加了很多交互控制上的便利,比如:素材替换、事件监听、动画混合、文字变更、物理碰撞等等。

在 2024 年春节群红包雨项目中几乎全部的素材都是 Lottie 动画素材:

4af8e382b0d1c28e3969993e3d7f697f.png

0736769d7b4100ed9acc77a2abe4b0b8.png

静态的 Lottie 素材结合 Simple Lottie 提供的动态交互能力就可以很方便的实现诸如红包点击、红包动态纹理、点中动画动态文字、大红包点击、连击动画动态数字等等。

举个例子,用户点中红包雨之后需要播放一个动画,整体是一个烟花的效果,需要随机展示不同的文字:

7e42529a36aea53847702d1aa412fe34.jpeg

对于这个需求,设计同学只需要提供一个固定的 Lottie 动画,然后再提供一些其它的文字素材;开发则需要在代码中首先从动画中查找到文字精灵,然后随机选取一张文字纹理,最后更新文字精灵的纹理即可。

b88a62f521e5a8fb9a137b56ca561889.png

特性支持

使用 Simple 引擎去渲染 Lottie 动画,还能在原有 Lottie 特性支持的基础上增加更多的能力。比如从动画素材上来说我们可以把原始 Lottie 动画产物中零散的图片合成一张雪碧图,减少资源请求数量,减少纹理个数,提升渲染性能:

e0251a69adabb2f0b55642088645813d.png

33136a79d563d4896cc8b666746a30e0.png

左侧是散图,右侧是雪碧图。除此之外甚至还能把图片转成压缩纹理,减少内存占用和加快渲染速度。

除了动画素材上的优化,还能给 Lottie 动画增加更多的渲染效果,比如:

粒子
6d1955696c83244ab161c9acdf71c793.jpeg
滤镜

Simple 引擎通过 Shader 实现了很多常用的滤镜效果,比如:

53c37f51345b32b0de9a5a3b8d50960b.png

d73d0a4e76634cf802a40700847c1089.png

左侧是模糊效果、右侧是颜色卷积效果。

自定义效果

基于 Simple 引擎提供的 WebGL 能力封装,还可以实现更多更丰富的自定义效果,比如:透明视频以及下面将要介绍 WebGL 帧差序列帧。

WebGL 帧差序列帧

帧差序列帧是一种基于 WebGL 1.0 标准的动画图片规范,由首帧图片、帧差图片(不透明帧差、半透明帧差)、帧差配置信息组成,一般包含 4 个文件:

2abdb79a4955255221847c183283e2a9.jpeg

背景

由于原始 Lottie 动画只支持少部分 AE 特性,对于不支持的特性设计师往往会把这些效果转成序列帧实现,这就会导致动画素材产物体积增加。而另一方面目前常用的视频、Apng、WebP 这些主流素材又各有各的问题,比如:

  • 视频存在兼容性问题、不能交互、对低端机来说存在一定的性能压力;

  • Apng、WebP 这些传统动画图片格式基本没怎么考虑帧间压缩:

4d659f28793f06ffe423fa7cb9a3393f.png

上图是一张 Apng 解码后的信息,IDAT 表示首帧、fdAT 表示后续帧,可以看到后续帧和首帧几乎一样大,也就是说对于这个素材生成的 Apng 效果和简单拼接的原始序列帧差不多。

资源体积优化

基于上述现状,如果能基于兼容性最好的 WebGL 1.0 标准去实现一些类视频的简单自定义帧间压缩算法, 就能在动画场景以更小的资源体积完美替代序列帧、 Apng WebP

2930afdb287ee8bb16d8288ad34ffa99.jpeg

对于一般素材帧差序列帧在体积上相比序列帧、 Apng WebP 会减少 50% 左右。

交互能力

帧差序列帧还能以更高的性能和提供任意时刻切任意帧的能力,实现一定的交互能力,从而满足一些轻互动场景的需求,对视频和 3D 模型形成差异化优势。

4f7127c6c4a27395de8120b1075cecf1.png

6668d3da94f67114b3a591786fc5c95e.jpeg

caa532be53baea4b0ac369d18729ddff.jpeg

我们以小火人、打年兽和徽章项目为例:

  • 小火人、年兽的动画状态是会随着用户的操作发生变化的,而视频是很难实现无缝的帧切换;

  • 徽章需要 360 度旋转展示,同时还需要响应用户的滑动操作,一般情况下这里只能使用 3D 模型,那么整个项目就得以传统 3D 项目的流程去做,一方面成本会高出很多,另一方面考虑实时渲染性能压力,效果上可能还做不到百分百还原。而采用帧差序列帧的方案去做,项目成本就会低很多,同时效果上也不会有任何折扣。

未来展望

以上即是我们团队在 Wasm 和 WebGL 上的一些尝试与思考,虽然取得了一定的突破,但是方案本身还有很多需要优化和完善的地方:

  • Wasm 标准依然在继续更新,SIMD、线程、垃圾回收、WASI 等新特性会进一步提升性能,同时可能会对现有引擎架构的升级产生很大影响;

  • 帧差序列帧目前的帧间压缩效率只是优于序列帧、Apng、WebP,和视频相比还有很大差距;在保持现有优势的前提下怎么更接近视频是充满挑战的问题;

  • Lottie 动画性能得到了优化,增加了很多能力;这些能力怎么高效率的开放给设计和开发去使用,怎么改进现有工作流效率,动效、轻互动的完美工作流需要满足哪些标准等等。

欢迎大家和我们团队一起探索和交流,共同推进技术的发展。

团队介绍

我们是抖音前端架构-互动体验技术团队,主要为字节跳动业务提供互动技术解决方案。技术产品包含面向互动 / 小游戏研发场景的 SAR Creator、高性能动效渲染引擎 Simple Engine、互动场景端能力套件 AnnieX 互动容器

在这些技术建设与业务落地上,和抖音前端-互动创作团队跨端框架团队、开放平台小游戏团队、用户增长-激励前端团队一同推进,不断探索字节跳动应用生态下的创新业务形态。

下期预告

下期主题是前端互动场景中的性能优化,将介绍前端互动页面在与宿主端共享有限进程资源的场景下遇到的性能问题及相应的解决方案,敬请期待。

往期回顾

2024 抖音欢笑中国年(一):招财神龙互动技术揭秘

2024 抖音欢笑中国年(二):AnnieX互动容器创新玩法解析

2024 抖音欢笑中国年(三):编辑器技巧与实践

2024 抖音欢笑中国年(四):渲染技术实践与探索

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/563271.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TCP 协议特性

1. TCP 基本认识 TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。 面向连接:一定是「一对一」才能连接,不能像 UDP 协议可以一个主机同时向多个主机发送消息,也就是一对多是无法做到的; 可靠的:无论的网络链…

【批量区域识别内容重命名】批量识别图片区域文字并重命名,批量图片部分识别内容重命文件,PDF区域识别提取重命名

我们在工作和生活中经常遇到这样的需求:比如将以下的图片区域识别进行重命名,批量识别后改成以时间和工作内容重命名,便于日后检索,快速查询 首先我们拍摄照片用到的是水印相机,这里的文字呢我们需要加个背景&#xff…

C++模版初阶----函数模版、类模版

C模版初阶 1. 泛型编程2. 函数模板2.1 函数模板概念2.2函数模板格式2.3 函数模板的原理2.4 函数模板的实例化2.5 函数模版的匹配原则 3. 类模板3.1 类模板的定义格式3.2 类模板的实例化 总结 1. 泛型编程 泛型编程 : 编写与类型无关的通用代码,是代码复用的一种手段…

利用STM32 HAL库实现USART串口通信,并通过printf重定向输出“Hello World“

一、开发环境 硬件:正点原子探索者 V3 STM32F407 开发板 单片机:STM32F407ZGT6 Keil版本:5.32 STM32CubeMX版本:6.9.2 STM32Cube MCU Packges版本:STM32F4 V1.27.1 上一篇使用STM32F407的HAL库只需1行代码实现US…

#STM32F407VET6(天空星)标准库和HAL驱动ILI9341

一、驱动方式:软件SPI,屏幕像素320*240 二、标准库含触摸,HAL库不含触摸 三、立创参考的文档 【立创天空星ST32F407VET6】模块移植手册 - 飞书云文档 (feishu.cn)https://lceda001.feishu.cn/wiki/MFNpw4STVi5ImikkcH1clWrlnqb 四、引脚分…

HIVE无法启动问题

​ 启动不了hive 一直在加载中! 问题:当我们打开电脑 想要学习hive时 我们却发现 它一直卡在启动页面 true一直后没有信息或者报错 原因:我们在之前学习时 在配置hdfs的高可用时(High Availability 简称HA) 高可用…

2024第十五届蓝桥杯省赛C++A组程序设计题解

ps:没有答案,考场上的代码,不一定对,大佬们轻喷,可以提供点更好的思路~ 试题C:训练士兵 解题思路 对于每次训练,需要考虑采用士兵单独训练还是组团训练的方式,故每次训练将所需训练…

【网站项目】“最多跑一次”小程序

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…

面试(06)————MySQL篇

目录 问题一:在MySQL中,如何定位慢查询? 方案一:开源工具 方案二:MySQL自带慢日志 模拟面试 问题二:这个SQL语句执行很慢,如何分析的呐? 模拟面试 问题三:了解过索引…

2024 IDM最新破解版及软件介绍

*IDM:信息时代的高效管理工具** 在快节奏的现代社会中,随着信息的爆炸式增长,如何高效、有序地管理信息成为每个人都需要面对的挑战。IDM,作为一种信息管理工具,正在逐渐受到人们的青睐。 IDM,全称Inform…

Android 出现4G模块无法上网问题

作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生在读,研究方向无线联邦学习 擅长领域:驱动开发,嵌入式软件开发,BSP开发 作者主页:一个平凡而乐于分享的小比特的个人主页…

【prometheus】k8s集群部署AlertManager实现邮件和钉钉告警

目录 一、AlertManager概述 1.1 alertmanager简介 1.2 AlertManager核心概念 1.2.1 分组 1.2.2 抑制 1.2.3 静默 1.2.4 客户的行为 1.2.5 高可用性 二、Alertmanager部署邮箱告警 2.1 邮箱配置 2.2 Alertmanager global和route路由配置 2.3 部署prometheus和alertM…

如何在PostgreSQL中创建一个新的数据库,并指定所有者?

文章目录 解决方案示例代码 PostgreSQL是一个强大的开源关系型数据库管理系统,它允许用户创建和管理多个数据库。在PostgreSQL中创建一个新的数据库并指定所有者是一个常见的操作。下面,我们将详细解释如何执行这一操作,并提供示例代码。 解…

Redis入门到通关之数据结构解析-SkipList

文章目录 ☃️概述☃️总结 ☃️概述 SkipList(跳表)是一种数据结构,用于实现有序元素的动态集合,它的设计目的是在有序链表的基础上通过增加多级索引来提高查找效率。 跳表的核心思想是在原始链表的基础上建立多层索引&#xf…

如何使用 Node.js 发送电子邮件全解和相关工具推荐

大多数Web应用程序都需要发送电子邮件。它可能用于注册、密码重置、状态报告,甚至是完整的市场营销活动,如新闻和促销。本教程解释了如何在Node.js中发送电子邮件,但其概念和挑战适用于您正在使用的任何系统。 你会在 npm 上找到大量与电子邮…

贪吃蛇的实现(一)

一、前言 学完C语言和数据结构的链表部分后,贪吃蛇的游戏也终于可以着手的实现了。对于贪吃蛇这个经典游戏,相信小伙伴们都不会太陌生,接下来我们 一起去剖析关于贪吃蛇游戏内部的一些逻辑结构和整体思维。 二、Win32 API 本章实现贪吃蛇会用…

读天才与算法:人脑与AI的数学思维笔记06_算法的进化

1. 现代算法 1.1. 知识不仅建立在真理之上,也建立在错误之上。 1.1.1. 卡尔荣格(Carl Jung) 1.2. 现代算法是可以自学的,尤其是推荐系统算法,它可以根据每个人的喜好推荐有趣的东西给我们 1.2.1. 算法通过与用户之…

PTA L2-052 吉利矩阵

题目 解析 这题考的是搜索剪枝 可行性剪枝: 即判断当前行(列)是否已经超过L和剩下的格子都填最大值是否小于L,若是则剪枝。 当前行数大于1时,判断上一个填完的行是否等于L,若否,则剪枝。 当前行…

一个简单的记工tkinter窗口

代码分享: 导入datetime模块,用于获取当前日期 import datetime as da 导入csv模块,用于读写csv文件 import csv 导入tkinter模块,用于创建窗口和按钮 from tkinter import * 创建主窗口 appTk() 设置窗口大小为1048x2048&#xff0…

【网络协议】 TCP与UDP协议区别及应用场景深度分析

1. TCP与UDP简介 1.1 TCP 1.1 定义 TCP(TransmissionControl Protocol)传输控制协议。 是一种可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。使用TCP的应…