webgl 游戏_如何选择 WebGL 框架和引擎?
Sugar 是我們從零開始開發的 BI 產品,可以不用寫 SQL 制作報表及大屏頁面,上半年我們發布了三維場景功能,可以放到大屏中展現:
為了實現這個功能,我們調研了大量 WebGL 相關框架和庫,整理了這篇文章,或許以后對你有幫助,趕緊先收藏吧。
引擎類型
WebGL 框架和引擎按照定位可以分成這三種類型:
- WebGL 封裝,定位是簡化 WebGL 開發,最大的特點是必須自己寫 GLSL 才能用。
- 渲染引擎,定位是三維物體及場景展示,一般會抽象出場景、相機、燈光等概念,上手門檻低,不需要自己寫 GLSL。
- 游戲引擎,定位是游戲開發,在前面的渲染引擎基礎上,還提供了骨骼動畫、物理引擎、AI、GUI 等功能,以及可視化編輯器來設計關卡,支撐大型游戲的開發。
WebGL 封裝
先說 WebGL 封裝,這種庫主要解決的問題是 WebGL 的 API 過于繁瑣。
WebGL 源自 OpenGL,它最早可以追溯到 1992 年,那個時候還是以 C 這種面向過程式的語言為主,所以 OpenGL 的 API 也是過程式的,對于熟悉面向對象的開發者來說,它的代碼看起來冗長且可讀性差,因此有必要對其進行封裝和簡化。
twgl.js
twgl.js?github.comtwgl.js 就是最典型的做法,比如創建一個最常見物體在 WebGL 中需要這樣寫,其中反復調用 bindBuffer 和 bufferData,很容易寫錯:
const positions = [1,1,-1,1,1,1,1,-1,1,1,-1,-1,-1,1,1,-1,1,-1,-1,-1,-1,-1,-1,1,-1,1,1,1,1,1,1,1,-1,-1,1,-1,-1,-1,-1,1,-1,-1,1,-1,1,-1,-1,1,1,1,1,-1,1,1,-1,-1,1,1,-1,1,-1,1,-1,1,1,-1,1,-1,-1,-1,-1,-1]; const normals = [1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1]; const texcoords = [1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1]; const indices = [0,1,2,0,2,3,4,5,6,4,6,7,8,9,10,8,10,11,12,13,14,12,14,15,16,17,18,16,18,19,20,21,22,20,22,23];const positionBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); const normalBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW); const texcoordBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texcoords), gl.STATIC_DRAW); const indicesBuffer = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);而使用 twgl.js 就能簡化成這樣:
const arrays = {position: [1,1,-1,1,1,1,1,-1,1,1,-1,-1,-1,1,1,-1,1,-1,-1,-1,-1,-1,-1,1,-1,1,1,1,1,1,1,1,-1,-1,1,-1,-1,-1,-1,1,-1,-1,1,-1,1,-1,-1,1,1,1,1,-1,1,1,-1,-1,1,1,-1,1,-1,1,-1,1,1,-1,1,-1,-1,-1,-1,-1],normal: [1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1],texcoord: [1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1],indices: [0,1,2,0,2,3,4,5,6,4,6,7,8,9,10,8,10,11,12,13,14,12,14,15,16,17,18,16,18,19,20,21,22,20,22,23], }; const bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);twgl 的定位只是減少重復代碼,并沒有進一步抽象,所以使用它和直接用 WebGL 在學習成本上沒太大區別,因此非常適合初學者,但也意味著它沒什么獨特的功能。
regl
regl?github.com和 twgl 單純簡化代碼相比,regl 提供了跟高層的抽象,將原本的過程式轉成了函數式,使得看起來更符合直覺,比如下面這個入門三角形比原生 WebGL 要少很多代碼。
const drawTriangle = regl({frag: `void main() {gl_FragColor = vec4(1, 0, 0, 1);}`,vert: `attribute vec2 position;void main() {gl_Position = vec4(position, 0, 1);}`,attributes: {position: [[0, -1], [-1, 0], [1, 1]]},count: 3 })regl 的原理是動態生成 WebGL 相關的 JavaScript 代碼然后執行,所以它比 twgl 能提供更加簡化的代碼,也能更靈活地設計對外 API,減少 WebGL 本身過程式帶來的限制,功能也更多,比如能自動處理狀態丟失。
從工程角度看 regl 做得很不錯,文檔詳盡,有 30000 單元測試,覆蓋率達到了 95%,還有工具來追蹤性能變化,可以很放心地使用。
但由于做了一層封裝,導致使用它和原生 WebGL 寫法差異較大,因此不適合對 WebGL 還不熟悉的初學者,但對于熟悉 WebGL 的開發者來說使用它的開發體驗不錯。
OGL
oframe/ogl?github.comOGL 的定位比較特別,它有點介于 WebGL 封裝和渲染引擎之間,比如它最簡單的這個例子:
import {Renderer, Camera, Transform, Box, Program, Mesh } from 'ogl'; const renderer = new Renderer(); const gl = renderer.gl; document.body.appendChild(gl.canvas); const camera = new Camera(gl); camera.position.z = 5; const scene = new Transform(); const geometry = new Box(gl);const program = new Program(gl, {vertex: `attribute vec3 position;uniform mat4 modelViewMatrix;uniform mat4 projectionMatrix;void main() {gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);}`,fragment: `void main() {gl_FragColor = vec4(1.0);}`, });const mesh = new Mesh(gl, {geometry, program}); mesh.setParent(scene); renderer.render({scene, camera});可以看到它一方面提供了渲染引擎才有的場景樹、相機等概念,另一方面又沒有材質和光源,所以需要自己寫 Shader 來完成基本渲染。
因此我覺得它比較適合 TA(Technical Artist) 使用,基于它開發可以不用了解太多 WebGL 的細節,專注于圖形學算法,而且它的 Uniform 變量名和 Three.js 是一樣的,網上找基于 Three.js 寫的例子都能直接用。
不過如果當成 WebGL 封裝,它成熟度不如 regl,因為缺乏單元測試使得預計會有不少 bug,而如果當成渲染庫在功能上又沒法和 Three.js 比,因此主要優勢似乎只有體積小了。
luma.gl
luma.gl?luma.glluma.gl 是 Uber 開發的,主要用它開發地理可視化框架,比如 Desk.gl 和 Kepler.gl,還有無人車數據可視化 AVS。
使用前面幾個庫要同時支持 WebGL 2.0 和 1.0 需要自己做兼容,而 luma.gl 可以自動解決這個問題,方便在支持 WebGL 2.0 的設備上優先使用 WebGL 2.0,比如直接調用 createVertexArray,不過這種 api 沒幾個,所以這個亮點倒是不顯著。
它的獨特功能其實是 Shader 模塊化拆分,這對于寫復雜的 Shader 很有幫助。
渲染引擎
由于 WebGL 本身只是光柵引擎,基于它開發需要了解矩陣變換并編寫著色器,所以 WebGL 學習門檻很高,光入門就要看特別長的文檔,比如 WebGL Fundamentals 這個教程系列就有 60 多篇文章。
WebGL Fundamentals?webglfundamentals.org相比之下使用渲染引擎就容易得多,它將其中的矩陣變化封裝成了相機、場景樹,并提供了材質和光源,運行時自動生成對應的 GLSL,使得即使完全不懂 WebGL 也能用,大大降低了門檻。
對于大部分應用而言,比起前面的 WebGL 封裝,最好還是選擇渲染引擎,因為大部分渲染引擎也提供了自定義 Shader 功能,也提供了 GPU 實例等功能,只是一般不能改渲染管線。
Filament
google/filament?github.comFilament 是 Google 基于 C++ 開發的跨平臺物理渲染引擎,支持 Android、iOS、Windows、Mac 等系統,還提供了基于 WebAssembly 的 Web 版本,它用在了 Google 地圖和搜索這兩個核心 APP 中,因此大概率會長期維護,不用擔心棄坑。
值得一提的是 Filament 的文檔寫得極好,相當于一本如何實現 PBR 的教材,可以學到很多圖形學的知識。
Physically Based Rendering in Filament?google.github.io盡管只是順帶支持 Web,但完善的實現使得它的渲染效果很突出,在渲染管線上使用了較為新穎的 Clustered forward renderer,因此能支持大量光源。
它生成的 wasm 文件有 2M,不算太大,我原本打算將它引入到 Sugar 中,但這個渲染庫在 Web 上使用有兩個缺點:
整體上我覺得它是學習 PBR 渲染實現原理的優秀項目,雖然暫時不適合在 Web 上用,但值得繼續關注。
Claygl
ClayGL?claygl.xyzClaygl 是 ECharts 核心開發者 pissang 大神的開發的 WebGL 游戲引擎,它還用在了 ECharts-gl 項目中,使得 ECharts 在三維圖表方面遠超所有競品,這點我在《如何挑選數據可視化框架及平臺 - 前端篇》里介紹過。
在我看來它最大的亮點是支持延遲著色,目前除了前面提到的 Filament 和后面的 LayaAir,其它 WebGL 引擎都是傳統的前向著色,這種管線在渲染時,會對每個物體計算所有光照的貢獻,類似如下的寫法:
for node of nodes:for light of lights:output += bdrf(node, light)這種實現的復雜度隨著光源和場景中對象的增加而增加,導致光源越多性能越差,這也是為什么在 Web 上看到的三維效果大部分都只使用一個主光源,類似下面這種效果,只有一個太陽光:
來自 https://demos.littleworkshop.fr/infinitown如果想實現接近現實世界的效果就必須支持多光源,尤其是室內和夜晚,比如類似下面這種,使用前向渲染性能太差,無法做到實時渲染。
來自 https://github.com/google/filament要解決這個問題只能使用延遲著色或者分簇(Clustered)前向著色,目前主流的桌面游戲引擎都是使用延遲著色,并配合前向著色來支持透明物體,相關細節推薦看看 lygyue:延遲渲染,ClayGL 也是目前唯一實現這種管線的開源渲染引擎。
不過在 WebGL 中實現延遲著色最大的問題是兼容性,因為它依賴 MTR(Multiple Render Targets) 技術,只有在 WebGL 2.0 下原生支持,在 WebGL 1.0 中必須依賴「WEBGL_draw_buffers」擴展,但它的兼容性較差,目前桌面瀏覽器的支持率也只有 71%,在手機上更是只有 2%,想在手機上使用只能等 WebGL 2.0 普及,但 iOS 一直默認不開啟,不知道要再等幾年了。
Litescene.js
https://github.com/jagenjo/litescene.js?github.comLitescene.js 主要用于開發 WebGL 場景編輯器 WebGLStudio,它其中有些 API 就是專門給編輯器用的,WebGLStudio 是少有的開源 WebGL 編輯器,功能很豐富,但使用體驗不好,給我的感受是必須用過 Unity 等編輯器才會用,上手門檻有點高。
這個項目的作者也是不容易,幾乎一個人開發了從 WebGL 到前端的所有功能,還開發了個前端 UI 庫 litegui,不過技術棧比較古老,一個人精力還是有限,代碼中有不少地方都沒空整理,比如加了個新文件但老的還沒空刪,而且也沒有 release 版本,所以不建議使用。
Hilo3d
https://github.com/hiloteam/Hilo3d?github.comHilo3d 是來自支付寶的項目,在 github 上最早提交時間是 2019 年 8 月,所以是這里面出現最晚的渲染引擎,在它之上還有個游戲引擎 Sein,它支持使用 Unity 作為場景編輯器,和 LayaAir 類似,但這個即是優點也是缺點,雖然省去了編輯器的開發,但導出效果很可能不一致,要反復調整。
這個渲染引擎最初目的是用于支付寶里自己研發的小游戲,所以重點是支持移動端,但這也將會是它的限制,比如追求體積小,圖形方面更重視性能而不是視覺效果,以及后期特效比較少等。
從提交看目前基本只有一個人,但看起來并不在 github 上開發,更像是拿 github 來定期發布版本。
osgjs
https://github.com/cedricpinson/osgjs?github.comogsl 借鑒了 OpenSceneGraph 的 API,很適合拿來構建三維場景,但這個項目已經停止了,主要原因是核心人員跑去創業了,它的核心開發人員之一成為了著名在線三維模型網站 Sketchfab 的 CTO,Sketchfab 的模型渲染器就是在它基礎上開發的,加上了后期特效等功能,算是 Web 領域效果最好的渲染器了。
xeogl
xeolabs/xeogl?github.comxeogl 很適合用來展示建筑及工業模型,它提供了標注、公告板以及相機動畫等功能,這些功能在其他引擎中都得自己實現。
不過這個項目作者不打算繼續維護了,估計是開源項目收益太小,作者目前主要在開發 xeokit,這個兩個項目的定位是一樣的,但 xeokit 商用要收費,一次性收 €2999,它對建筑類的項目很友好,內置了許多 BIM 相關的定制功能,比如對 ifc 格式和 BIMServer 的支持,還有支持截面瀏覽,所以使用它可以節省大量開發成本。
不過它在渲染效果方面的功能不多,后期特效只有一個 SAO,因此更適合樸實無華的工程項目展示。
A-Frame
aframevr/aframe?github.comA-Frame 是專注做 VR 的渲染庫,最早是 Mozilla 開發的,目前主要是 Supermedium 的兩個工程師和一個谷歌的工程師兼職開發,它的底層渲染基于 Threejs,提供了 inspector 功能,能很方便測試效果。
不過我每次玩 VR 都暈到吐,所以再也不關注這個領域了,暈問題是人腦的機制,只能靠幾萬年的進化來解決,而且還得是不暈的人比暈的人有生存優勢,所以我是等不到 VR 會火的那天了。
游戲引擎
游戲引擎在渲染器的基礎上增加了面向游戲開發的各種功能,包括 AI、物理、編輯器等,工作量巨大,比起圖形學算法,更重要還有工程能力,完整的游戲引擎功能可以參考《Game Engine Architechture》這本書,下面的架構圖就是來自這本書,可以看到它所覆蓋的面相當廣。
Unreal Engine
目前最火的游戲引擎是 Unreal Engine 和 Unity,它們都可以使用 Emscripten 編譯出 WebAssembly 版本的項目,直接運行在瀏覽器中。
幾年前在 WebGL 領域中最讓人印象深刻的 demo 就是 Unreal 就和 Firefox 合作的這個項目,當時我也試過,在等了十幾分鐘加載幾十 M 的 JS 文件后終于跑起來了,但非常卡。
知乎視頻?www.zhihu.com這個 demo 是 2014 年的,但渲染效果放到今天來看都很驚艷,秒殺絕大部分基于 Three.js/Babylon.js 開發的項目,甚至再過幾年 Three.js/Babylon.js 也做不到,因為需要靠編輯器來優化間接光照。
前段時間我嘗試編譯過專門給移動端的 SunTemple 項目,在我的黑蘋果 RX 5700 XT 上雖然不卡了,但體積太大,光引擎本身的 wasm 文件就有 82MB,數據文件也有 180MB,這樣的體積是不可能放在 Web 上運行的,難怪沒人用。
估計也是因為沒什么人用,Unreal Engine 從 4.24 版本開始不默認提供這個功能,只作為擴展存在,交給社區,要用得自己編譯一個,所以 Unreal Engine 目前已經基本放棄了 HTML5 版本。
Unity
相比之下 Unity 編譯出來的體積小得多,自帶的簡單 3D 項目編譯出 wasm 只有 4M,所以雖然也很少人用,但至少在線上有真實見到過幾個。
值得一提的是 Unity 還在開發專門針對小游戲的 Project Tiny 版本,相當于一個精簡版的 Unity,它輸出的體積更小,比如這個官方的 Tiny Racing 項目 wasm 只有 607k,即便是所有模型和圖片加起來的體積也只有 4.4M,雖然這個項目還在預覽階段,很多重要功能缺失,但 Unity 目前普及度高,所以它未來有不小潛力,但它在國內的發展取決于官方的是否重視,比如會不會支持微信等。
Godot
https://godotengine.org/?godotengine.orgGodot 是目前最火的開源游戲引擎,它有 1182 個貢獻者,提交很頻繁,最近在開發的 4.0 版本,將支持 Vulkan API,并在渲染方面做了加強,比如支持 SDFGI。
它也能導出 WebGL 版本,但只是「能導出」,并沒有專門優化過,拿幾個材質測試了一下生成的 wasm 有 20M,但性能太差,在我的 i9 + RX 5700 XT 上都卡成 PPT,而且卡頓這個問題官方也不打算修了,預計 Godot 短期不會在 Web 領域有所發展,只能等它未來或許會支持 WebGPU 了。
Three.js
https://threejs.org/?threejs.orgThree.js 是最知名的 WebGL 項目,Contributions 人數高達 1313,和 React 是一個量級的,盡管它自身的定位只是渲染引擎,但社區硬是把不少游戲引擎的功能都加上了,比如物理引擎、貼花、動畫等,在源碼中有大量例子,很適合學習,但不少重要功能,比如 gltf 加載器,都是放在 examples 目錄里,讓人感覺很不正式。
Three.js 的歷史幾乎和 WebGL 一樣長,它早在 2010 年 7 月 7 日就支持 WebGL 渲染了,那個時候 WebGL 規范還在草案中,要等到 2011 年 3 月才正式發布,恐怕這就是為什么提到 WebGL 大家都會想到 Three.js,它大概是第一個支持 WebGL 的引擎。
由于知名度最高,Three.js 最大的優勢就是社區強大,搜索問題能找到很多答案,也有非常多開源和商業項目使用,比如 Google 的 WebGL Globe、model-viewer、NASA 的 WorldWind、Autodesk 的 Forge Viewer 等。
但 Three.js 在版本管理方面很不專業,到現在都還沒采用 semver 版本命名規范,每次發布都是一個叫 rXXX 的版本,我見過不少基于 Three.js 的項目都是固定在某個版本不敢升級了,比如 Autodesk 就提到過。
雖然 Three.js 有很多人使用,但因為整體代碼質量一般,我只推薦用來學習,而不是用在正式項目中。
PlayCanvas
https://github.com/playcanvas/engine?github.comPlayCanvas 雖然開源了游戲引擎,但編輯器只有在線服務,所以它的文檔都是介紹如何使用在線編輯器來制作三維場景,并沒有直接使用這個引擎的入門文檔,要用只能通過 example 和 api 來了解,看起來官方并不希望大家直接使用引擎,所以如果不想用它的在線編輯器,這個引擎就只適合學習過其它引擎的開發者。
從引擎功能角度看弱于 Three.js 和 Babylon,但成熟度比 Three.js 好,Three.js 的很多功能是第三方貢獻的,質量參差不齊,注釋也很少。
雖然它沒使用延遲著色,但提供了運行時 bake 的功能,也能高效支持靜態多光源。
PlayCanvas 其實在 2017 年被 Snap 悄悄收購了,被期望于制作 Snap 上的 HTML5 游戲。
Egret
egret-labs/egret3d?github.comEgret 和后面介紹的 LayaAir 和 cocos 都是國內創業公司開發的游戲引擎,Egret 最早是通過一款《圍住神經貓》的 HTML5 游戲莫名其妙火的,它最早只支持 2D,但也在 2018 年 5 月推出了開源的 Egret 3D。
Egret 3D 引擎使用了 ECS 架構,所以它的編輯器提供了類似 Unity 那樣添加組件的能力。
但 Egret 3D 開源后沒多久就陷入停滯狀態了,最新發布的版本是 2018 年 9 月,據說是在重構新版,然而已經過去一年了,可能 3D 并不是公司的重點,開源的版本甚至連 license 都沒說明,加上文檔比較簡陋,所以不推薦使用。
LayaAir
https://github.com/layabox/LayaAir?github.comLayaBox 公司最早推出的是 LayaFlash 工具來將 Flash 頁游裝成 HTML5 版本,隨著 Flash 的沒落,他們又開發了基于 Web 技術的 LayaAir 引擎。
LayaAir 的三維編輯器主要依賴 Unity,它甚至不能直接使用 WebGL 中最常用的 glTF 格式,要使用三維模型必須先導入到 Unity 中,然后再通過插件轉成 LayaAir 所使用的格式。
比起 Three.js/Babylon,LayaAir 有兩個比較大的優勢,一個是對小程序支持友好,這個算是國內特色,Three.js/Babylon j的核心開發者也沒條件測試,所以實際用起來容易遇到 bug,玩玩需要改引擎本身代碼才能解決;另一個是近期實現了 Clustered Forward 渲染,可以支持大量光源。
LayaAir 還提供了生成原生 Android/iOS 程序的 LayaNative,這里并非使用 WebView,所以更容易過審。
但需要注意 LayaAir 只是源碼開放,并不是真正的開源項目,使用前需要仔細閱讀它的協議,比如未經授權是不允許對引擎代碼進行修改的,免費使用需要加 LayaBox 的 logo。
從提交歷史看,LayaAir 提交量最多的開發者在今年 4 月份忽然停止了,似乎是被阿里挖走了,不知道對引擎本身的發展會有多大影響。
cocos
Cocos引擎_游戲開發引擎?www.cocos.comcocos 曾經是最流行的 2D 手游引擎,但隨著游戲逐漸轉向 3D,它在 3D 方面和 Unity 差距太大,就漸漸淡出大家的視野了。
cocos 所屬的觸控科技本來打算 2014 年在美國上市,但由于對估值不滿意,尤其是 cocos2d-x 的 MIT 協議被認為價值幾乎為零,所以最后放棄了上市,具體細節可以看看創始人的回答cocos2dx 還有未來么? - 陳昊芝的回答,其中還提到了和 Unity 的故事,比如本來還想收購 Unity 但被拒了,在放棄上市后,觸控經歷了很多危機,人數也收縮為之前的 1/5,從那時起 cocos2d-x 其實就在走下坡路了,逐漸被 Unity 超越。
盡管很艱難,觸控一直沒放棄引擎的開發,在 2019 年 10 月發布了 Cocos Creator 3D,和 cocos2d-x 基于 C++ 不同,Cocos Creator 3D 是基于 TypeScript 開發的 WebGL 引擎。
在協議方面,Cocos Creator 3D 吸取了 cocos2d-x 的教訓,和 LayaAir 一樣只是源碼開放,它也有一份定制的協議,有很多限制,需要仔細閱讀。
盡管 Cocos Creator 3D 很想成為 Unity,編輯器在很多細節點上都參考了 Unity,比如資源管理的 .meta 文件,基于 ECS 的組件機制等,但 WebGL 的限制使得它只能用做小游戲的引擎,因為 OpenGL ES 2.0 功能的缺失,雖然可以發布到微信、百度、支付寶等平臺上,但在重度游戲領域沒法和 Unity 競爭。
引擎方面功能和 LayaAir 類似,不過它有動畫、例子編輯器,在編輯器方面比 LayaAir 好得多,不依賴 Unity,不過因為使用了前向著色,同樣不能支持多光源,雖然它基于 AABB 包圍盒做了光源裁剪,但這種方式的性能比較依賴場景光源和物體的分布情況,比如物體很大又有很多小光源的時候,幾乎裁剪不掉幾個光源。
Babylon
https://babylonjs.com/?babylonjs.com最后壓軸的是 Babylon,它也是 Sugar 最終采用的 WebGL 引擎,不僅功能強大,代碼質量也很高,TypeScript 類型完善,幾乎每個函數都有注釋。
我個人的使用體會是 Babylon 雖然入門要復雜點,但功能成熟度要比 Three.js 高不少,Three.js 至今在 gLTF 的支持上還有 bug,而 Babylon 是唯一通過所有測試的框架,如果要深入使用 gLTF,Babylon 是最好選擇,因為它還支持大量擴展,比如 KHR_mesh_quantization、KHR_draco_mesh_compression、KHR_texture_basisu、MSFT_lod 等,這些擴展能顯著減小體積和提升性能。
Babylon 在材質方面功能豐富,除了基礎的 PBR,還提供了用于皮膚的次表面渲染 SubSurface、用于車漆的 ClearCoat、用于布料的 Sheen,以及用于光盤之類的各向異性材質 Anisotropy 等等。
在后期特效方面有 Lut 顏色校正、Tonemap 映射、SSAO、鏡面反射、Bloom 等常見特效,還有基于屏幕的反射 SSR(Screen Space Reflections)。
目前 Babylon 在渲染方面也是使用最傳統的前向著色,如果要改造成類似 ClayGL 那樣的延遲著色成本太高,兼容性也不好,所以最好的選擇是用分簇來減少光源,這個想法在 2017 年就有提出,但然后就沒有然后了。
除了在渲染方面的功能很多,Babylon 的周邊工具也很豐富,最近還推出了類似 UE4 藍圖的材質編輯器。
我個人不喜歡使用藍圖這種方式來開發業務邏輯,因為復雜場景下信息密度太低了,大量線條看起來很累,但用藍圖來開發材質卻很方便,因為著色器不好調試,而在藍圖中可以方便預覽每個節點的效果,極大提升效率,不過也可能是我在著色器方面比較水。
不過 Babylon 的這個材質編輯器目前功能還比較弱,缺少流程控制語句等功能,和 Unreal Engine 差距很大。
另一個 Babylon 中最實用的工具是 Inspector,它可以像瀏覽器的開發者工具那樣,選中場景中的某個節點,就能查看和修改它的屬性和材質等,實時看到效果,比不斷改代碼調整方便多了。
另外 Babylon 還開發了可以直接運行在桌面的 BabylonNative,和 LayaNative 類似,基于封裝了跨平臺的渲染(基于 bgfx)、網絡等接口,這樣編譯出一個桌面 Babylon 項目就不需要像 Electron 那樣附帶一個百兆的 Chromium 了,然而在桌面領域游戲引擎多如牛毛,競爭過于激烈,BabylonNative 看起來希望不大。
Babylon 最后一個亮點是正在開發 WebGPU 版本,而其他引擎都沒開始做,所以等 WebGPU 發布后,Babylon 應該是首批支持的,將得到更多關注。
小結
前面說了那么多,如果沒空看的話可以記一下我的看法:
- 對于一般 WebGL 開發,推薦使用 Babylon.js。
- 如果要支持微信小程序,最好用國內的 LayaAir 和 Cocos,但需要注意它們只是源碼開放,并不是無條件免費使用,需要仔細閱讀使用協議。
- 如果只想寫原生 WebGL 特效,建議用 regl。
- 如想支持大量光源和后期特效,又不需要支持 iOS,用 Claygl。
- 如果熟悉 Unity,直接用它導出 WebGL 也是可行的。
后記:WebGL 為什么沒火起來?
10 年前 WebGL 剛出來的時候我很期待,因為可以在 Web 上做出酷炫的三維效果了,看起來前景一片光明,然而現在除了小游戲,其它地方幾乎沒有人使用,也很少前端工程師了解,為什么呢?在我看來主要是這幾方面的原因:
Web 的下一代技術是 WebGPU,它能極大提升性能,具體提升多少呢,在 WebGPU 官方 wiki 中拿了 Babylon 的例子:
https://www.babylonjs.com/demos/webgpu/forestwebgl?www.babylonjs.comhttps://www.babylonjs.com/Demos/WebGPU/forestWebGPU.html?www.babylonjs.com我測試后發現 CPU 時間從 20ms 降到了 0.08ms,FPS 從 30 增加到了穩定 60,提升非常明顯,是不是很期待 WebGPU 的未來?
然而這個對比并不公平,這里的性能提升不完全是 WebGPU 帶來的,我猜是開發者在演講前發現效果不明顯,就先優化了一下,下面這段代碼是 WebGPU 版本中多出的部分,如果加到 WebGL 版本中也能明顯提升性能,因為每次循環的時候不需要重新計算了,可以顯著減少 CPU 時間。
// After all the meshes creation, freeze as much as we can to improve perfs. optimizeScene(scene);const optimizeScene = function(scene) {scene.freezeMaterials();scene.meshes.forEach((m) => {m.isPickable = false;m.alwaysSelectAsActiveMesh = true;m.freezeWorldMatrix();});setTimeout(() => {scene.freezeActiveMeshes();}, 1000); }后面有空我會單獨介紹 WebGPU,趕緊關注哈哈。
總結
以上是生活随笔為你收集整理的webgl 游戏_如何选择 WebGL 框架和引擎?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Java核心技术(卷I)] - vsc
- 下一篇: 国内可用语料库