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