pfan123 / Articles

经验文章
169 stars 25 forks source link

WebGL 框架选型 #93

Open pfan123 opened 3 years ago

pfan123 commented 3 years ago

WebGL(Web图形库)是一个 JavaScript API,可在任何兼容的 Web 浏览器中渲染高性能的交互式 3D 和 2D 图形,而无需使用插件。WebGL 通过引入一个与 OpenGL ES 2.0 非常一致的 API 来做到这一点,该 API 可以在 HTML5 <canvas>元素中使用。 这种一致性使 API 可以利用用户设备提供的硬件图形加速。

目前支持 WebGL 的浏览器有:Firefox 4+, Google Chrome 9+, Opera 12+, Safari 5.1+, Internet Explorer 11+和Microsoft Edge build 10240+;然而, WebGL一些特性也需要用户的硬件设备支持。

WebGL 2 API引入了对大部分的 OpenGL ES 3.0 功能集的支持; 它是通过WebGL2RenderingContext界面提供的。

<canvas> 元素也被 Canvas API 用于在网页上进行 2D 图形处理。

目前 WebGL 技术使用越来越普及,已大量运用到智慧城市、3D 的数据可视化(大数据BI)、3D 游戏开发、3D 绘图软件、 3D 产品 / 物体展示交互等领域。

接下来几年,VR 应用的风靡,转战 Unity3D 做了商场的互动游戏,为“某钢”做了全厂的能源管道。

实际中webgl应用的领域有哪些?

Unity3D 游戏创作,在Unity3D编辑器中安装HTML5游戏资源导出插件,可用于HTML5游戏开发。 相关教程: https://ke.qq.com/course/170225?taid=3993744059832561

WebGL 框架分类

WebGL 框架和引擎按照定位可以分成这三种类型:

WebGL 封装

先说 WebGL 封装,这种库主要解决的问题是 WebGL 的 API 过于繁琐。

WebGL 源自 OpenGL,它最早可以追溯到 1992 年,那个时候还是以 C 这种面向过程式的语言为主,所以 OpenGL 的 API 也是过程式的,对于熟悉面向对象的开发者来说,它的代码看起来冗长且可读性差,因此有必要对其进行封装和简化。

twgl.js

twgl.js 就是最典型的 WebGL 封装 做法,主要解决的问题是 WebGL 的 API 过于繁琐,比如创建一个最常见物体在 WebGL 中需要这样写,其中反复调用 bindBuffer 和 bufferData,很容易写错,而使用 twgl.js 就能大量的简化,但是twgl 的定位是减少重复代码,并没有进一步抽象,所以使用它和直接用 WebGL 在学习成本上没太大区别,因此非常适合初学者,但也意味着它没什么独特的功能。

OGL

OGL 的定位比较特别,它有点介于 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 是 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 多篇文章。

相比之下使用渲染引擎就容易得多,它将其中的矩阵变化封装成了相机、场景树,并提供了材质和光源,运行时自动生成对应的 GLSL,使得即使完全不懂 WebGL 也能用,大大降低了门槛。

对于大部分应用而言,比起前面的 WebGL 封装,最好还是选择渲染引擎,因为大部分渲染引擎也提供了自定义 Shader 功能,也提供了 GPU 实例等功能,只是一般不能改渲染管线。

Filament

Filament 是 Google 基于 C++ 开发的跨平台物理渲染引擎,支持 Android、iOS、Windows、Mac 等系统,还提供了基于 WebAssembly 的 Web 版本,它用在了 Google 地图和搜索这两个核心 APP 中,因此大概率会长期维护,不用担心弃坑。

值得一提的是 Filament 的文档写得极好,相当于一本如何实现 PBR 的教材,可以学到很多图形学的知识。

Physically Based Rendering in Filamentgoogle.github.io

尽管只是顺带支持 Web,但完善的实现使得它的渲染效果很突出,在渲染管线上使用了较为新颖的 Clustered forward renderer,因此能支持大量光源。

它生成的 wasm 文件有 2M,不算太大,但这个渲染库在 Web 上使用有两个缺点:

  1. 核心是 C++ 写的,如果功能不满足只能去改 C++,而这几乎是必须的,因为暴露给 JavaScript 的 API 很少,最简单的点击交互都不支持,各个组件的设置也很少,比如相机要实现无交互时自动旋转就得改 C++ 代码,不熟悉 C++ 将寸步难行。
  2. 只支持 WebGL 2.0,这点比较致命,导致无法在 iOS 的浏览器上使用,看了一下它有调用 glDrawBuffers,但不清楚用于做什么。

整体上我觉得它是学习 PBR 渲染实现原理的优秀项目,虽然暂时不适合在 Web 上用,但值得继续关注。

Claygl

使用 ECharts GL 实现基础的三维可视化

Claygl 是 ECharts 核心开发者 pissang 大神的开发的 WebGL 游戏引擎,它还用在了 ECharts-gl 项目中,可以在ECharts官网示例中新出现了很多GL图形。

它最大的亮点是支持延迟着色,目前除了前面提到的 Filament 和后面的 LayaAir,其它 WebGL 引擎都是传统的前向着色,这种管线在渲染时,会对每个物体计算所有光照的贡献,如果想实现接近现实世界的效果就必须支持多光源,尤其是室内和夜晚,面夹角越多,计算的阴影面越多,使用前向渲染性能太差,无法做到实时渲染。

Litescene.js

Litescene.js 主要用于开发 WebGL 场景编辑器 WebGLStudio,它其中有些 API 就是专门给编辑器用的,WebGLStudio 是少有的开源 WebGL 编辑器,功能很丰富,但使用体验不好,给我的感受是必须用过 Unity 等编辑器才会用,上手门槛有点高。

这个项目的作者也是不容易,几乎一个人开发了从 WebGL 到前端的所有功能,还开发了个前端 UI 库 litegui,不过技术栈比较古老,一个人精力还是有限,代码中有不少地方都没空整理,比如加了个新文件但老的还没空删,而且也没有 release 版本,所以不建议使用。

Hilo3d

Hilo3d 是来自支付宝的项目,在 github 上最早提交时间是 2019 年 8 月,所以是这里面出现最晚的渲染引擎,在它之上还有个游戏引擎 Sein,它支持使用 Unity 作为场景编辑器,和 LayaAir 类似,但这个即是优点也是缺点,虽然省去了编辑器的开发,但导出效果很可能不一致,要反复调整。

这个渲染引擎最初目的是用于支付宝里自己研发的小游戏,所以重点是支持移动端,但这也将会是它的限制,比如追求体积小,图形方面更重视性能而不是视觉效果,以及后期特效比较少等。

从提交看目前基本只有一个人,但看起来并不在 github 上开发,更像是拿 github 来定期发布版本。

osgjs

ogsl 借鉴了 OpenSceneGraph 的 API,很适合拿来构建三维场景,但这个项目已经停止了,主要原因是核心人员跑去创业了,它的核心开发人员之一成为了著名在线三维模型网站 SketchfabCTO,Sketchfab 的模型渲染器就是在它基础上开发的,加上了后期特效等功能,算是 Web 领域效果最好的渲染器了。

xeogl

xeogl 很适合用来展示建筑及工业模型,它提供了标注、公告板以及相机动画等功能,这些功能在其他引擎中都得自己实现。

不过这个项目作者不打算继续维护了,估计是开源项目收益太小,作者目前主要在开发 xeokit,这个两个项目的定位是一样的,但 xeokit 商用要收费,一次性收 €2999,它对建筑类的项目很友好,内置了许多 BIM 相关的定制功能,比如对 ifc 格式和 BIMServer 的支持,还有支持截面浏览,所以使用它可以节省大量开发成本。

不过它在渲染效果方面的功能不多,后期特效只有一个 SAO,因此更适合朴实无华的工程项目展示。

A-Frame

A-Frame 是专注做 VR 的渲染库,最早是 Mozilla 开发的,目前主要是 Supermedium 的两个工程师和一个谷歌的工程师兼职开发,它的底层渲染基于 Threejs,提供了 inspector 功能,能很方便测试效果。

SceneJS

它是针对计算机辅助设计的要求。 开源的JavaScript3D引擎,特别适合需要高精度细节的模型需求,比如工程学和医学上常用的高精度模

优点 专门用于快速绘制大量单独连接的对象,而没有像阴影、反射等游戏引擎效果。SceneJS的API和JSON相似,它学习起来很简单。

缺点 相关社群几乎没有,中国很少人用。缺少碰撞检测等功能。加载大模型时速度较慢。需提供正在载入信息提示,尽可能提高用户体验。

ThingJS

强大的3d引擎,简化模型制作,提高开发效率,在线开发部署,支持离线部署。ThingJS面向物联网的3D可视化PaaS开发平台.基于WebGL兼容各种浏览器及移动设备.零门槛、高效率、低成本开发各类3D应用。

优点 ThingJS和其他开发工具相比,站在了更高的封装层面, 用尽可能简洁的接口,直接提供了场景的加载与展示、物联网设备的创建与特效;还提供了信息点、线路、管线、区域、热图、粒子、动画等丰富功能;提供了摄影机控制、第一人称行走、寻路

导航和视点线路工具;可扩展的界面、头顶信息牌、内嵌视频监控等丰富的信息展示方式。这些接口大部分已经在在线例子中可以找到,可以边改参数边看到效果;帮助用户以最快的速度 学习、开发与部署。

缺点 不是开源的。ThingJS所定位的物联网可视化应用,侧重宏观场景表现,并不针对局部细节的效果,而且由于WebGL技术的性能局限,在性能上不能和Unity等原生程序相比

游戏引擎

游戏引擎在渲染器的基础上增加了面向游戏开发的各种功能,包括 AI、物理、编辑器等,工作量巨大,比起图形学算法,更重要还有工程能力,完整的游戏引擎功能可以参考《Game Engine Architechture》这本书,下面的架构图就是来自这本书,可以看到它所覆盖的面相当广。

Unity

相比之下 Unity 编译出来的体积小得多,自带的简单 3D 项目编译出 wasm 只有 4M,所以虽然也很少人用,但至少在线上有真实见到过几个。

值得一提的是 Unity 还在开发专门针对小游戏的 Project Tiny 版本,相当于一个精简版的 Unity,它输出的体积更小,比如这个官方的 Tiny Racing 项目 wasm 只有 607k,即便是所有模型和图片加起来的体积也只有 4.4M,虽然这个项目还在预览阶段,很多重要功能缺失,但 Unity 目前普及度高,所以它未来有不小潜力,但它在国内的发展取决于官方的是否重视,比如会不会支持微信等。

Godot

Godot引擎是一个功能打包的跨平台游戏引擎,用于从统一界面创建2D和3D游戏。它提供了一套全面的通用工具,让用户可以专注于制作游戏,而不必重新发明轮子。游戏可以一键导出到许多平台,包括主要的桌面平台(Linux、macOS、Windows)、移动平台(Android、iOS)以及基于Web的平台(HTML5)和控制台。最近在开发的 4.0 版本,将支持 Vulkan API,并在渲染方面做了加强,比如支持 SDFGI

BabylonJS

Babylon.js是一款WebGL开发框架。 适合做中大型项目,尤其是多种媒体混杂的或者是游戏项目VR体验项目。

优点 功能较为全面,功能比较丰富、灵活、模型显示不失真。有微软背景,有不少的demo,有较详细的api文档,有供测试的平台,有提供3dsmax转换模型的插件,许多非常牛叉的新特性,并对已有功能进行了完善。更方便快捷地完成光线、轮船纹理、海浪等的3D建模,从而带来最佳的呈现效果。

缺点 学习难度大、周期长,需要进行大量深入的学习与研究。另外,在模型文件较大或较多时,浏览器打开时会等待较长时间,中文资料很少,没有系统的中文教程,论坛也会被墙。

ThreeJS

是一款 webGL 开源框架,易用、简单、直观的方式封装了 3D 图形编程中常用的对象。在开发中使用了很多图形引擎的高级技巧,提高了性能。内置了很多常用对象和极易上手的工具,功能强大。

优点 国内用的比较多,所以中文的资料也会比较多,有比较系统的中文教程如从入门到精通。用的人比较多,所以相关的qq群较多,群里的人也较多,接触到的大牛应该也会比较多。

缺点 没有提供一些基础建模软件的插件,比如3dsmax的模型导出插件,虽然说提供一些读3ds格式,fbx格式的场景。要配合更多扩展库完成,因为你可能会需要联网通信功能的封装、声音普通控制甚至高级频谱控制、输入设备信息的处理等诸多渲染以外的功能。国内学习资料多,但加载速度慢、缺少碰撞检测等功能。

LayaboxJS

LayaAir引擎支持精灵、矢量图、文本、富文本、位图字体、动画、骨骼、音频与视频、滤镜、事件、加载、缓动、时间、网络、UI系统、物理系统、TiledMap、prtocol等API;支持开发2D、3D、VR的产品研发,支持Canvas与WebGL模式,支持同时发布为HTML5、Flash、APP(IOS、安卓)多种版本。

优点 极致性能:LayaAir优先使用webgl渲染,如果webgl不可用,自动无缝转为canvas渲染,引擎设计过程中处处以性能为优先原则,LayaAir是为裸跑而设计的HTML5引擎。

轻量易用:LayaAir API设计上追求精简,简单易用,上手容易,引擎本身非常注意自身大小,是目前同等功能最小的HTML5引擎。

支持多语言开发:LayaAir同时支持ActionScript3、TypeScript、JavaScript三种语言开发HTML使用任意一种自己喜欢的语言开发即可。

缺点 有些功能与问题,官方文档没提到,网上搜到同样问题的帖子,却没人回答。作为一个开源免费的引擎,不是每个问题,官方都能准时解答的,甚至你发个帖子,很长一段时间都没有一个答案,这时只能自己慢慢摸索一下了。

Egret

Egret 和后面介绍的 LayaAir 和 cocos 都是国内创业公司开发的游戏引擎,Egret 最早是通过一款《围住神经猫》的 HTML5 游戏莫名其妙火的,它最早只支持 2D,但也在 2018 年 5 月推出了开源的 Egret 3D

Egret 3D 引擎使用了 ECS 架构,所以它的编辑器提供了类似 Unity 那样添加组件的能力。

但 Egret 3D 开源后没多久就陷入停滞状态了,最新发布的版本是 2018 年 9 月,据说是在重构新版,然而已经过去一年了,可能 3D 并不是公司的重点,开源的版本甚至连 license 都没说明,加上文档比较简陋,所以不推荐使用。

cocos

cocos 曾经是最流行的 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 包围盒做了光源裁剪,但这种方式的性能比较依赖场景光源和物体的分布情况,比如物体很大又有很多小光源的时候,几乎裁剪不掉几个光源。

PlayCanvas

PlayCanvas 虽然开源了游戏引擎,但编辑器只有在线服务,所以它的文档都是介绍如何使用在线编辑器来制作三维场景,并没有直接使用这个引擎的入门文档,要用只能通过 example 和 api 来了解,看起来官方并不希望大家直接使用引擎,所以如果不想用它的在线编辑器,这个引擎就只适合学习过其它引擎的开发者。

从引擎功能角度看弱于 Three.js 和 Babylon,但成熟度比 Three.js 好,Three.js 的很多功能是第三方贡献的,质量参差不齐,注释也很少。

虽然它没使用延迟着色,但提供了运行时 bake 的功能,也能高效支持静态多光源。

PlayCanvas 其实在 2017 年被 Snap 悄悄收购了,被期望于制作 Snap 上的 HTML5 游戏。

小结

前面介绍了那么多,整体来说:

WebGL2.0标准的发展和普及如何?,目前 WebGL 2.0 在Firefox和Chrome桌面版本上已得到很好的支持,但 Safari 和 iOS 支持进度比较慢,而 WebGPU 标准也要出来了,WebGL 2.0 可能面临 WebGPU 替换。

Other Resources

如何选择 WebGL 框架和引擎?

WebGL

WebGPU学习(一): 开篇