2024 抖音歡笑中國年之Wasm、WebGL 在互動技術(shù)中的創(chuàng)新應(yīng)用
前言
隨著 Web 前端技術(shù)的不斷發(fā)展,越來越多的新興技術(shù)方案被引入到 Web 開發(fā)中,其中 Wasm 和 WebGL 作為前端領(lǐng)域的兩大利器,為開發(fā)者帶來了更多的可能性。
本文將結(jié)合2024 年抖音歡笑中國年的部分項目,重點介紹如何利用 Wasm 和 WebGL 對目前流行的一些前端互動技術(shù)(比如 Lottie、渲染引擎、動畫圖片等)進(jìn)行創(chuàng)新和實踐,利用 Wasm 和 WebGL 等新技術(shù)方案的特性和優(yōu)勢提升業(yè)務(wù)性能和流暢度,給用戶帶來更好的體驗。
Simple 渲染引擎
WebAssembly(Wasm)是一種可以在 Web 瀏覽器中運行,提供比 JavaScript 更高的性能,并且支持多種編程語言的全新的字節(jié)碼格式;基于其高性能的優(yōu)勢,我們團(tuán)隊嘗試將其應(yīng)用到渲染場景中,推出了基于 Wasm + WebGL 的高性能、輕量化的 Simple 渲染引擎。
以期借助于 Wasm 的高性能計算,以 Simple 引擎為基礎(chǔ),保持輕量化的同時,解決目前前端動效和輕互動場景主流技術(shù)方案如 Lottie 動畫、動畫圖片(序列幀、 Apng 、WebP)、JS 渲染引擎等存在的能力受限、資源體積大、性能較低等問題。
引擎架構(gòu)
考慮到前端用戶學(xué)習(xí)和使用成本,Simple 引擎使用 TypeScript 語言開發(fā)上層接口,主要是利用 TS 封裝簡單對象,同時做類型提示方便前端用戶使用,另外還提供盡可能高性能的方式和 Wasm 進(jìn)行交互;底層則使用 C/C++,主要處理計算工作,比如:矩陣計算、圖形計算、動畫計算、動態(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 的計算性能優(yōu)勢,Simple 引擎相比主流的 JS 渲染引擎,比如:PixiJS 6.3、Cocos 2.4 在 Spine 動畫、精靈旋轉(zhuǎn)、精靈跳動、圖形水平移動等基準(zhǔn)性能測試場景中取得了不俗的表現(xiàn):
以上測試數(shù)據(jù)來自 Android OPPO Find X1 抖音 跨端框架 V8 環(huán)境,可以看到基于 Wasm 的 Simple 引擎相比基于 JS 的引擎性能提升明顯,計算任務(wù)越復(fù)雜,性能收益越大。
計算任務(wù)復(fù)雜度:骨骼動畫 > 圖形計算 > 旋轉(zhuǎn)變換 > 位移變換
測試代碼
100 個 Spine 動畫 Simple 和 Cocos 2.4 測試代碼如下:
- Cocos 2.4
- Simple
兼容性
從 2015 年 Wasm 項目正式啟動到現(xiàn)在,經(jīng)過多年的發(fā)展 Wasm 規(guī)范不斷完善和擴(kuò)展,目前主流的瀏覽器已經(jīng)全面支持 Wasm 技術(shù);同時 Simple 引擎最早在 2022年7月啟動,之后在直播、財經(jīng)、頭條、音樂、小說等多個業(yè)務(wù)場景中落地,并在 2024 年初獲得了在春節(jié)項目中應(yīng)用的機(jī)會。
從數(shù)據(jù)來看抖音跨端框架中使用 Wasm 的用戶占比高達(dá) 96.97% ,對于不支持 Wasm 的情況也可以使用 Simple 引擎編譯的 asm.js 版本來進(jìn)行降級。
經(jīng)過一年多的反復(fù)實踐與驗證,總得來說 Simple 引擎兼容性表現(xiàn)穩(wěn)定可靠。
Lottie WebGL 渲染
Lottie WebGL 渲染是利用上文提到的 Wasm + WebGL 渲染引擎去渲染 Lottie 動畫的方案,在幾乎完美還原 Lottie 動畫的基礎(chǔ)上,利用引擎封裝好的相關(guān)機(jī)制(事件、渲染對象)擴(kuò)展 Lottie 動畫的交互控制能力,豐富其特性支持,以及基于 Wasm + WebGL 渲染提升動畫性能。
性能收益
Lottie 是動畫 Airbnb 公司開源的跨平臺動畫框架,支持將 AE 中設(shè)計的動畫導(dǎo)出為 Json 協(xié)議,是前端最流行的動畫協(xié)議;但是在 Web 上官方只提供了三種渲染方式(SVG、Canvas 2D、HTML),并沒有支持 WebGL:
而前端最流行的那些 JS WebGL 渲染引擎也沒有直接支持 Lottie 動畫,這就會帶來三個問題:
官方渲染方案性能低
SVG、HTML 不適合處理大量元素的動畫,而 Canvas 2D 的使用方式?jīng)Q定了它很難充分利用緩存機(jī)制,因此官方提供的這三種渲染方案其實性能是偏低的,會在較多、較復(fù)雜動畫場景遭遇性能瓶頸。
如上圖所示某 Lottie 動畫在 Chrome 6 倍降速模擬移動端設(shè)備的性能表現(xiàn),Lottie SVG 每幀耗時 5.77 毫秒,而 Simple Lottie 每幀耗時僅 1.10 毫秒,性能提升近 6 倍。
離屏 Canvas 渲染性能低
目前主流的 JS WebGL 渲染引擎只能使用離屏 Canvas 的方式去渲染 Lottie 動畫,這種方式需要先創(chuàng)建一個離屏的 Canvas 然后用 Lottie 官方提供的 Canvas 2D 方式把動畫的當(dāng)前狀態(tài)渲染到離屏 Canvas 中,接著再把這個離屏的 Canvas 用紋理的方式上傳到 GPU,如果動畫更新還需要重復(fù)這個流程。
相對復(fù)雜的渲染流程會導(dǎo)致其性能較低:
如上圖所示,12 * 18 個 Lottie 動畫在 i7 Mac Chrome 上測試,右側(cè) WebGL 直接渲染 Lottie 動畫比左側(cè)離屏 Canvas 渲染幀數(shù)高了 35 fps,性能提升近 3 倍。
JS 圖形計算性能低
提升 Lottie 動畫性能,除了要考慮渲染性能,還需要考慮計算性能,比如上面兩個例子中的 Lottie 動畫更多是圖片元素,但是矢量圖形也是 Lottie 動畫中非常重要的功能。
如果基于目前主流的 JS WebGL 渲染引擎去渲染 Lottie 動畫,在以矢量圖形為主的 Lottie 動畫中對比 Lottie 官方提供的 SVG 或者 Canvas 甚至?xí)霈F(xiàn)性能劣化的情況:
可以看到左側(cè) SVG 在動畫峰值每幀僅需 6.26 毫秒,而右側(cè) PixiJS 在動畫峰值每幀需要 11.68 毫秒。
基于 JS WebGL 渲染引擎渲染 Lottie 動畫在矢量圖形場景出現(xiàn)性能劣化最主要原因在于 SVG 的計算在瀏覽器封裝的 Native 模塊中進(jìn)行,而 JS WebGL 渲染引擎的計算在 JS 中進(jìn)行,哪怕是幾乎優(yōu)化到極致的 PixiJS 受限于 JS 也只能在圖片元素等部分 Lottie 動畫中取得性能優(yōu)化收益;因此只有采用 Simple 引擎這種 Wasm + WebGL 的方案才能徹底、全面優(yōu)化 Lottie 動畫的性能:
相同場景 Simple Lottie 在動畫峰值每幀僅需 5.35 毫秒(這其中還包含了 JS 動畫參數(shù)插值計算部分,后續(xù)這部分 JS 計算也下沉 Wasm ,整體估計還能優(yōu)化 1 毫秒 )。
交互控制
使用 Simple 引擎直接去渲染 Lottie 動畫,除了性能上的收益之外,還利用引擎提供的能力增加了很多交互控制上的便利,比如:素材替換、事件監(jiān)聽、動畫混合、文字變更、物理碰撞等等。
在 2024 年春節(jié)群紅包雨項目中幾乎全部的素材都是 Lottie 動畫素材:
靜態(tài)的 Lottie 素材結(jié)合 Simple Lottie 提供的動態(tài)交互能力就可以很方便的實現(xiàn)諸如紅包點擊、紅包動態(tài)紋理、點中動畫動態(tài)文字、大紅包點擊、連擊動畫動態(tài)數(shù)字等等。
舉個例子,用戶點中紅包雨之后需要播放一個動畫,整體是一個煙花的效果,需要隨機(jī)展示不同的文字:
對于這個需求,設(shè)計同學(xué)只需要提供一個固定的 Lottie 動畫,然后再提供一些其它的文字素材;開發(fā)則需要在代碼中首先從動畫中查找到文字精靈,然后隨機(jī)選取一張文字紋理,最后更新文字精靈的紋理即可。
特性支持
使用 Simple 引擎去渲染 Lottie 動畫,還能在原有 Lottie 特性支持的基礎(chǔ)上增加更多的能力。比如從動畫素材上來說我們可以把原始 Lottie 動畫產(chǎn)物中零散的圖片合成一張雪碧圖,減少資源請求數(shù)量,減少紋理個數(shù),提升渲染性能:
左側(cè)是散圖,右側(cè)是雪碧圖。除此之外甚至還能把圖片轉(zhuǎn)成壓縮紋理,減少內(nèi)存占用和加快渲染速度。
除了動畫素材上的優(yōu)化,還能給 Lottie 動畫增加更多的渲染效果,比如:
粒子
濾鏡
Simple 引擎通過 Shader 實現(xiàn)了很多常用的濾鏡效果,比如:
左側(cè)是模糊效果、右側(cè)是顏色卷積效果。
自定義效果
基于 Simple 引擎提供的 WebGL 能力封裝,還可以實現(xiàn)更多更豐富的自定義效果,比如:透明視頻以及下面將要介紹 WebGL 幀差序列幀。
WebGL 幀差序列幀
幀差序列幀是一種基于 WebGL 1.0 標(biāo)準(zhǔn)的動畫圖片規(guī)范,由首幀圖片、幀差圖片(不透明幀差、半透明幀差)、幀差配置信息組成,一般包含 4 個文件:
背景
由于原始 Lottie 動畫只支持少部分 AE 特性,對于不支持的特性設(shè)計師往往會把這些效果轉(zhuǎn)成序列幀實現(xiàn),這就會導(dǎo)致動畫素材產(chǎn)物體積增加。而另一方面目前常用的視頻、Apng、WebP 這些主流素材又各有各的問題,比如:
- 視頻存在兼容性問題、不能交互、對低端機(jī)來說存在一定的性能壓力;
- Apng、WebP 這些傳統(tǒng)動畫圖片格式基本沒怎么考慮幀間壓縮:
上圖是一張 Apng 解碼后的信息,IDAT 表示首幀、fdAT 表示后續(xù)幀,可以看到后續(xù)幀和首幀幾乎一樣大,也就是說對于這個素材生成的 Apng 效果和簡單拼接的原始序列幀差不多。
資源體積優(yōu)化
基于上述現(xiàn)狀,如果能基于兼容性最好的 WebGL 1.0 標(biāo)準(zhǔn)去實現(xiàn)一些類視頻的簡單自定義幀間壓縮算法, 就能在動畫場景以更小的資源體積完美替代序列幀、 Apng 、 WebP 。
對于一般素材幀差序列幀在體積上相比序列幀、 Apng 、 WebP 會減少 50% 左右。
交互能力
幀差序列幀還能以更高的性能和提供任意時刻切任意幀的能力,實現(xiàn)一定的交互能力,從而滿足一些輕互動場景的需求,對視頻和 3D 模型形成差異化優(yōu)勢。
我們以小火人、打年獸和徽章項目為例:
- 小火人、年獸的動畫狀態(tài)是會隨著用戶的操作發(fā)生變化的,而視頻是很難實現(xiàn)無縫的幀切換;
- 徽章需要 360 度旋轉(zhuǎn)展示,同時還需要響應(yīng)用戶的滑動操作,一般情況下這里只能使用 3D 模型,那么整個項目就得以傳統(tǒng) 3D 項目的流程去做,一方面成本會高出很多,另一方面考慮實時渲染性能壓力,效果上可能還做不到百分百還原。而采用幀差序列幀的方案去做,項目成本就會低很多,同時效果上也不會有任何折扣。
未來展望
以上即是我們團(tuán)隊在 Wasm 和 WebGL 上的一些嘗試與思考,雖然取得了一定的突破,但是方案本身還有很多需要優(yōu)化和完善的地方:
- Wasm 標(biāo)準(zhǔn)依然在繼續(xù)更新,SIMD、線程、垃圾回收、WASI 等新特性會進(jìn)一步提升性能,同時可能會對現(xiàn)有引擎架構(gòu)的升級產(chǎn)生很大影響;
- 幀差序列幀目前的幀間壓縮效率只是優(yōu)于序列幀、Apng、WebP,和視頻相比還有很大差距;在保持現(xiàn)有優(yōu)勢的前提下怎么更接近視頻是充滿挑戰(zhàn)的問題;
- Lottie 動畫性能得到了優(yōu)化,增加了很多能力;這些能力怎么高效率的開放給設(shè)計和開發(fā)去使用,怎么改進(jìn)現(xiàn)有工作流效率,動效、輕互動的完美工作流需要滿足哪些標(biāo)準(zhǔn)等等。