2024 抖音歡笑中國年之Wasm、WebGL 在互動(dòng)技術(shù)中的創(chuàng)新應(yīng)用

前言
隨著 Web 前端技術(shù)的不斷發(fā)展,越來越多的新興技術(shù)方案被引入到 Web 開發(fā)中,其中 Wasm 和 WebGL 作為前端領(lǐng)域的兩大利器,為開發(fā)者帶來了更多的可能性。
本文將結(jié)合2024 年抖音歡笑中國年的部分項(xiàng)目,重點(diǎn)介紹如何利用 Wasm 和 WebGL 對(duì)目前流行的一些前端互動(dòng)技術(shù)(比如 Lottie、渲染引擎、動(dòng)畫圖片等)進(jìn)行創(chuàng)新和實(shí)踐,利用 Wasm 和 WebGL 等新技術(shù)方案的特性和優(yōu)勢(shì)提升業(yè)務(wù)性能和流暢度,給用戶帶來更好的體驗(yàn)。
Simple 渲染引擎
WebAssembly(Wasm)是一種可以在 Web 瀏覽器中運(yùn)行,提供比 JavaScript 更高的性能,并且支持多種編程語言的全新的字節(jié)碼格式;基于其高性能的優(yōu)勢(shì),我們團(tuán)隊(duì)嘗試將其應(yīng)用到渲染場(chǎng)景中,推出了基于 Wasm + WebGL 的高性能、輕量化的 Simple 渲染引擎。
以期借助于 Wasm 的高性能計(jì)算,以 Simple 引擎為基礎(chǔ),保持輕量化的同時(shí),解決目前前端動(dòng)效和輕互動(dòng)場(chǎng)景主流技術(shù)方案如 Lottie 動(dòng)畫、動(dòng)畫圖片(序列幀、 Apng 、WebP)、JS 渲染引擎等存在的能力受限、資源體積大、性能較低等問題。
引擎架構(gòu)
考慮到前端用戶學(xué)習(xí)和使用成本,Simple 引擎使用 TypeScript 語言開發(fā)上層接口,主要是利用 TS 封裝簡單對(duì)象,同時(shí)做類型提示方便前端用戶使用,另外還提供盡可能高性能的方式和 Wasm 進(jìn)行交互;底層則使用 C/C++,主要處理計(jì)算工作,比如:矩陣計(jì)算、圖形計(jì)算、動(dòng)畫計(jì)算、動(dòng)態(tài)合批等;
Simple 引擎目前的渲染管線主要以 2D 為主,也分為兩部分:JS 部分負(fù)責(zé)處理數(shù)據(jù)量少但是 GL 調(diào)用頻繁的操作,Wasm 部分則相反負(fù)責(zé)處理數(shù)據(jù)量多但是 GL 調(diào)用少的操作,盡可能達(dá)到性能最優(yōu)解。
整體架構(gòu)如下:

性能收益
受益于 Wasm 的計(jì)算性能優(yōu)勢(shì),Simple 引擎相比主流的 JS 渲染引擎,比如:PixiJS 6.3、Cocos 2.4 在 Spine 動(dòng)畫、精靈旋轉(zhuǎn)、精靈跳動(dòng)、圖形水平移動(dòng)等基準(zhǔn)性能測(cè)試場(chǎng)景中取得了不俗的表現(xiàn):

以上測(cè)試數(shù)據(jù)來自 Android OPPO Find X1 抖音 跨端框架 V8 環(huán)境,可以看到基于 Wasm 的 Simple 引擎相比基于 JS 的引擎性能提升明顯,計(jì)算任務(wù)越復(fù)雜,性能收益越大。
計(jì)算任務(wù)復(fù)雜度:骨骼動(dòng)畫 > 圖形計(jì)算 > 旋轉(zhuǎn)變換 > 位移變換
測(cè)試代碼
100 個(gè) Spine 動(dòng)畫 Simple 和 Cocos 2.4 測(cè)試代碼如下:
- Cocos 2.4

- Simple

兼容性
從 2015 年 Wasm 項(xiàng)目正式啟動(dòng)到現(xiàn)在,經(jīng)過多年的發(fā)展 Wasm 規(guī)范不斷完善和擴(kuò)展,目前主流的瀏覽器已經(jīng)全面支持 Wasm 技術(shù);同時(shí) Simple 引擎最早在 2022年7月啟動(dòng),之后在直播、財(cái)經(jīng)、頭條、音樂、小說等多個(gè)業(yè)務(wù)場(chǎng)景中落地,并在 2024 年初獲得了在春節(jié)項(xiàng)目中應(yīng)用的機(jī)會(huì)。
從數(shù)據(jù)來看抖音跨端框架中使用 Wasm 的用戶占比高達(dá) 96.97% ,對(duì)于不支持 Wasm 的情況也可以使用 Simple 引擎編譯的 asm.js 版本來進(jìn)行降級(jí)。
經(jīng)過一年多的反復(fù)實(shí)踐與驗(yàn)證,總得來說 Simple 引擎兼容性表現(xiàn)穩(wěn)定可靠。
Lottie WebGL 渲染
Lottie WebGL 渲染是利用上文提到的 Wasm + WebGL 渲染引擎去渲染 Lottie 動(dòng)畫的方案,在幾乎完美還原 Lottie 動(dòng)畫的基礎(chǔ)上,利用引擎封裝好的相關(guān)機(jī)制(事件、渲染對(duì)象)擴(kuò)展 Lottie 動(dòng)畫的交互控制能力,豐富其特性支持,以及基于 Wasm + WebGL 渲染提升動(dòng)畫性能。
性能收益
Lottie 是動(dòng)畫 Airbnb 公司開源的跨平臺(tái)動(dòng)畫框架,支持將 AE 中設(shè)計(jì)的動(dòng)畫導(dǎo)出為 Json 協(xié)議,是前端最流行的動(dòng)畫協(xié)議;但是在 Web 上官方只提供了三種渲染方式(SVG、Canvas 2D、HTML),并沒有支持 WebGL:

而前端最流行的那些 JS WebGL 渲染引擎也沒有直接支持 Lottie 動(dòng)畫,這就會(huì)帶來三個(gè)問題:
官方渲染方案性能低
SVG、HTML 不適合處理大量元素的動(dòng)畫,而 Canvas 2D 的使用方式?jīng)Q定了它很難充分利用緩存機(jī)制,因此官方提供的這三種渲染方案其實(shí)性能是偏低的,會(huì)在較多、較復(fù)雜動(dòng)畫場(chǎng)景遭遇性能瓶頸。


如上圖所示某 Lottie 動(dòng)畫在 Chrome 6 倍降速模擬移動(dòng)端設(shè)備的性能表現(xiàn),Lottie SVG 每幀耗時(shí) 5.77 毫秒,而 Simple Lottie 每幀耗時(shí)僅 1.10 毫秒,性能提升近 6 倍。
離屏 Canvas 渲染性能低
目前主流的 JS WebGL 渲染引擎只能使用離屏 Canvas 的方式去渲染 Lottie 動(dòng)畫,這種方式需要先創(chuàng)建一個(gè)離屏的 Canvas 然后用 Lottie 官方提供的 Canvas 2D 方式把動(dòng)畫的當(dāng)前狀態(tài)渲染到離屏 Canvas 中,接著再把這個(gè)離屏的 Canvas 用紋理的方式上傳到 GPU,如果動(dòng)畫更新還需要重復(fù)這個(gè)流程。
相對(duì)復(fù)雜的渲染流程會(huì)導(dǎo)致其性能較低:


如上圖所示,12 * 18 個(gè) Lottie 動(dòng)畫在 i7 Mac Chrome 上測(cè)試,右側(cè) WebGL 直接渲染 Lottie 動(dòng)畫比左側(cè)離屏 Canvas 渲染幀數(shù)高了 35 fps,性能提升近 3 倍。
JS 圖形計(jì)算性能低
提升 Lottie 動(dòng)畫性能,除了要考慮渲染性能,還需要考慮計(jì)算性能,比如上面兩個(gè)例子中的 Lottie 動(dòng)畫更多是圖片元素,但是矢量圖形也是 Lottie 動(dòng)畫中非常重要的功能。
如果基于目前主流的 JS WebGL 渲染引擎去渲染 Lottie 動(dòng)畫,在以矢量圖形為主的 Lottie 動(dòng)畫中對(duì)比 Lottie 官方提供的 SVG 或者 Canvas 甚至?xí)霈F(xiàn)性能劣化的情況:


可以看到左側(cè) SVG 在動(dòng)畫峰值每幀僅需 6.26 毫秒,而右側(cè) PixiJS 在動(dòng)畫峰值每幀需要 11.68 毫秒。
基于 JS WebGL 渲染引擎渲染 Lottie 動(dòng)畫在矢量圖形場(chǎng)景出現(xiàn)性能劣化最主要原因在于 SVG 的計(jì)算在瀏覽器封裝的 Native 模塊中進(jìn)行,而 JS WebGL 渲染引擎的計(jì)算在 JS 中進(jìn)行,哪怕是幾乎優(yōu)化到極致的 PixiJS 受限于 JS 也只能在圖片元素等部分 Lottie 動(dòng)畫中取得性能優(yōu)化收益;因此只有采用 Simple 引擎這種 Wasm + WebGL 的方案才能徹底、全面優(yōu)化 Lottie 動(dòng)畫的性能:

相同場(chǎng)景 Simple Lottie 在動(dòng)畫峰值每幀僅需 5.35 毫秒(這其中還包含了 JS 動(dòng)畫參數(shù)插值計(jì)算部分,后續(xù)這部分 JS 計(jì)算也下沉 Wasm ,整體估計(jì)還能優(yōu)化 1 毫秒 )。
交互控制
使用 Simple 引擎直接去渲染 Lottie 動(dòng)畫,除了性能上的收益之外,還利用引擎提供的能力增加了很多交互控制上的便利,比如:素材替換、事件監(jiān)聽、動(dòng)畫混合、文字變更、物理碰撞等等。
在 2024 年春節(jié)群紅包雨項(xiàng)目中幾乎全部的素材都是 Lottie 動(dòng)畫素材:


靜態(tài)的 Lottie 素材結(jié)合 Simple Lottie 提供的動(dòng)態(tài)交互能力就可以很方便的實(shí)現(xiàn)諸如紅包點(diǎn)擊、紅包動(dòng)態(tài)紋理、點(diǎn)中動(dòng)畫動(dòng)態(tài)文字、大紅包點(diǎn)擊、連擊動(dòng)畫動(dòng)態(tài)數(shù)字等等。
舉個(gè)例子,用戶點(diǎn)中紅包雨之后需要播放一個(gè)動(dòng)畫,整體是一個(gè)煙花的效果,需要隨機(jī)展示不同的文字:

對(duì)于這個(gè)需求,設(shè)計(jì)同學(xué)只需要提供一個(gè)固定的 Lottie 動(dòng)畫,然后再提供一些其它的文字素材;開發(fā)則需要在代碼中首先從動(dòng)畫中查找到文字精靈,然后隨機(jī)選取一張文字紋理,最后更新文字精靈的紋理即可。

特性支持
使用 Simple 引擎去渲染 Lottie 動(dòng)畫,還能在原有 Lottie 特性支持的基礎(chǔ)上增加更多的能力。比如從動(dòng)畫素材上來說我們可以把原始 Lottie 動(dòng)畫產(chǎn)物中零散的圖片合成一張雪碧圖,減少資源請(qǐng)求數(shù)量,減少紋理個(gè)數(shù),提升渲染性能:


左側(cè)是散圖,右側(cè)是雪碧圖。除此之外甚至還能把圖片轉(zhuǎn)成壓縮紋理,減少內(nèi)存占用和加快渲染速度。
除了動(dòng)畫素材上的優(yōu)化,還能給 Lottie 動(dòng)畫增加更多的渲染效果,比如:
粒子

濾鏡
Simple 引擎通過 Shader 實(shí)現(xiàn)了很多常用的濾鏡效果,比如:


左側(cè)是模糊效果、右側(cè)是顏色卷積效果。
自定義效果
基于 Simple 引擎提供的 WebGL 能力封裝,還可以實(shí)現(xiàn)更多更豐富的自定義效果,比如:透明視頻以及下面將要介紹 WebGL 幀差序列幀。
WebGL 幀差序列幀
幀差序列幀是一種基于 WebGL 1.0 標(biāo)準(zhǔn)的動(dòng)畫圖片規(guī)范,由首幀圖片、幀差圖片(不透明幀差、半透明幀差)、幀差配置信息組成,一般包含 4 個(gè)文件:

背景
由于原始 Lottie 動(dòng)畫只支持少部分 AE 特性,對(duì)于不支持的特性設(shè)計(jì)師往往會(huì)把這些效果轉(zhuǎn)成序列幀實(shí)現(xiàn),這就會(huì)導(dǎo)致動(dòng)畫素材產(chǎn)物體積增加。而另一方面目前常用的視頻、Apng、WebP 這些主流素材又各有各的問題,比如:
- 視頻存在兼容性問題、不能交互、對(duì)低端機(jī)來說存在一定的性能壓力;
- Apng、WebP 這些傳統(tǒng)動(dòng)畫圖片格式基本沒怎么考慮幀間壓縮:

上圖是一張 Apng 解碼后的信息,IDAT 表示首幀、fdAT 表示后續(xù)幀,可以看到后續(xù)幀和首幀幾乎一樣大,也就是說對(duì)于這個(gè)素材生成的 Apng 效果和簡單拼接的原始序列幀差不多。
資源體積優(yōu)化
基于上述現(xiàn)狀,如果能基于兼容性最好的 WebGL 1.0 標(biāo)準(zhǔn)去實(shí)現(xiàn)一些類視頻的簡單自定義幀間壓縮算法, 就能在動(dòng)畫場(chǎng)景以更小的資源體積完美替代序列幀、 Apng 、 WebP 。

對(duì)于一般素材幀差序列幀在體積上相比序列幀、 Apng 、 WebP 會(huì)減少 50% 左右。
交互能力
幀差序列幀還能以更高的性能和提供任意時(shí)刻切任意幀的能力,實(shí)現(xiàn)一定的交互能力,從而滿足一些輕互動(dòng)場(chǎng)景的需求,對(duì)視頻和 3D 模型形成差異化優(yōu)勢(shì)。



我們以小火人、打年獸和徽章項(xiàng)目為例:
- 小火人、年獸的動(dòng)畫狀態(tài)是會(huì)隨著用戶的操作發(fā)生變化的,而視頻是很難實(shí)現(xiàn)無縫的幀切換;
- 徽章需要 360 度旋轉(zhuǎn)展示,同時(shí)還需要響應(yīng)用戶的滑動(dòng)操作,一般情況下這里只能使用 3D 模型,那么整個(gè)項(xiàng)目就得以傳統(tǒng) 3D 項(xiàng)目的流程去做,一方面成本會(huì)高出很多,另一方面考慮實(shí)時(shí)渲染性能壓力,效果上可能還做不到百分百還原。而采用幀差序列幀的方案去做,項(xiàng)目成本就會(huì)低很多,同時(shí)效果上也不會(huì)有任何折扣。
未來展望
以上即是我們團(tuán)隊(duì)在 Wasm 和 WebGL 上的一些嘗試與思考,雖然取得了一定的突破,但是方案本身還有很多需要優(yōu)化和完善的地方:
- Wasm 標(biāo)準(zhǔn)依然在繼續(xù)更新,SIMD、線程、垃圾回收、WASI 等新特性會(huì)進(jìn)一步提升性能,同時(shí)可能會(huì)對(duì)現(xiàn)有引擎架構(gòu)的升級(jí)產(chǎn)生很大影響;
- 幀差序列幀目前的幀間壓縮效率只是優(yōu)于序列幀、Apng、WebP,和視頻相比還有很大差距;在保持現(xiàn)有優(yōu)勢(shì)的前提下怎么更接近視頻是充滿挑戰(zhàn)的問題;
- Lottie 動(dòng)畫性能得到了優(yōu)化,增加了很多能力;這些能力怎么高效率的開放給設(shè)計(jì)和開發(fā)去使用,怎么改進(jìn)現(xiàn)有工作流效率,動(dòng)效、輕互動(dòng)的完美工作流需要滿足哪些標(biāo)準(zhǔn)等等。



























