如何看待Three.js/WebGL等前端3D技术?

本文整理来自 Web Infra 大咖面对面:活动,本文为现场 AMA 翻译,略作可读性优化。

主持人: 大家好,欢迎来到今天的大咖面对面活动。本次活动由 ByteDance Web Infra 主办,稀土掘金协办。很荣幸邀请到我们的嘉宾,经验丰富、知识渊博的图形编程工程师 Ricardo Cabello[1]。Ricardo 作为 Three.js 作者广为人知。Three.js 是一个轻量的跨浏览器 API 库,通常用来在 Web 浏览器中创建并显示动态的 3D 图像。它极大提升了对 3D 视觉效果和其他虚拟感官环境进行编辑和互动的体验。在今天的活动中,我们预先收集了大家关于 Three.js、WebGL、虚拟现实技术的相关问题。在深入讨论这些问题之前,让我们热烈欢迎我们的嘉宾 Ricardo。你好 Ricardo,你那边怎么样?

Ricardo@mrdoob: 挺好的,纽约现在是清晨。

主持人: 很棒啊。早安纽约。好的,那请你先为我们做个自我介绍吧。

Ricardo@mrdoob: 好呀,我的名字叫 Ricardo。我以前是一名图形设计师,后来成为了软件工程师。现在这两种身份兼而有之,同时还在做开源维护者。有时我会更像一个设计师,只不过是设计软件。我目前在 Google 工作。主要专注于提升开发者在 Web 端进行 3D、AR 以及 VR 开发时的体验。同时,如你所知我也需要寻找人们开发网站时的痛点,这也是对 Three.js 在上述领域里起作用来说,很重要的东西。( Three.js 的产生)也是挺随机的。

主持人: 好的,这很棒。那么在我们提那些尖锐的问题之前,先聊聊关于你自己的事情吧,一些学习技巧或者行业观点之类的。第一个问题是,你是怎样自学了编程并选择 Web 图形这个方向作为主业的呢?

Ricardo@mrdoob: 在欧洲有一个挺大的叫做 Demoscene[2] 的社区,大家都会写代码,并且展示当时的计算机都能做得到哪些事情。比如我们就会在 Amiga[3]Commodore 64[4] 这种计算机上彼此展示自己的成就。这都是互联网年代之前的事儿了。人们会在那里学习编程,也会一起组队竞争、来创造一些 demo 以展示自己的能力。我就是从那里开始的。当时我十岁的时候我的哥哥就开始参与这些集会,然后我也就会帮着一起做一些图形处理。这都是在有 Photoshop 以前了。我是从这里开始了解到其他人在做的东西。渐渐地我也想学习编程,想制作我自己的特效与动效。后来我二十岁左右的时候就开始做专业的 Flash 工作,再后来就从 Flash 转向了 JavaScript。这的确实像是一个进化过程。最开始是从 Demoscene 大会开始的。我从那里受到了启发,看着那里的人们都在做的东西。我也没有专门去专业学校学习,一切都发展得很自然。

主持人: 所以,换句话说,你是受到启发然后才决定创造属于自己的框架?

Ricardo@mrdoob: 对,基本上是这样,从那时就开始了。由于我学习了很多的知识,像是很多人都关心的实时动画,那时我有一个很棒的点子,我知道我需要亲自实现一个。比如 Papervision3D,以及另外一个像 Three.js 的库。我总是看到有新的库重新被创造出来,所以我就想要自己做一个适合我的需求的库,然后最后把它开源了。当然,我把 Three.js 开源的时候它还很不成熟,但是当时也有许多人开始帮助我。这是让我想创造自己的框架的部分原因,还有一部分原因是,我已经在图形动效上花了这么多时间。我既然已经把它当作爱好钻研了 10 年,我应该做出些什么。我喜欢在已有的东西上反复扩展和迭代。我已经在这方向上投入了这么多年,这是我所能做的,今后也无法改变。

主持人: 但是这不是很让人兴奋吗?想象一下十年前,你自己是否都无法想象如今的成就?

Ricardo@mrdoob: 对对,当然的了。我记得当时和同伴们参与这些竞赛时 -- 他们现在还在参与着 -- 但是我当时参与的时候图形动效方面的未来非常不明确。现在是有点意义的,但是在 2000 年搞实时动效就有点... 怎么说呢?你没法把这些东西卖出去。

主持人: 确实是。

Ricardo@mrdoob: 就不知道自己为什么要学这些技能,也不知道之后怎么样会用得上这些技能。但是后来当我们有了 WebGL 和网页上的 3D 后,就突然发现:哦,我之前学的和我现在了解的东西,我以为我是在浪费时间,现在却变得非常有用。我对我的运气感到很惊喜,我之前做这只是出于兴趣爱好。但是当时确实是,你能在电脑上做一些 3D 场景,但是在 HTML 中能把文字显示好就已经很好了。到后面才发现我能做这些贡献。然后因为我们在有 WebGL 前就开始做 Three.js 了,我也没有过任何期待,也不知道这个项目会不会成功。开发 Three.js 的原因更多的是:这是我需要的东西,并且看起来也有其他人需要,那我就继续完善它吧。同时我做这个项目也能用到我的知识与技能。每次看到新的网页或项目用到 Three.js 都会让我感到惊喜。比如 NASA 用 Three.js 展示火星车着陆。这种事情是完全无法预料到的。我很高兴 Three.js 能在那种方面发挥作用。

主持人: 我觉得很多人都能感同身受,因为大多数人都会有不知自己前进方向的阶段,或者不清楚自己现在做的事情以后会不会有用。我就把这理解成开发过程中遇到的困难吧。那么你在这个过程中遇到的其他困难都有些什么呢?

Ricardo@mrdoob: 我依然不太认为自己是软件工程师,而更多的是一位被强推上工程师位置的图形设计师。因为没有人想去做这个工作,所以最后还是要自己做。

我自己在看一些 James Dyson[5] (戴森公司创始人)的访谈,就是那个做风扇和吸尘器的人。他做调研的时候惊讶地发现设计师和工程师在完全不同的地方办公。他说工程师的工作场所应该和同一个产品的设计师在一起,而且即使是工程师也应当有一定的设计能力。

我觉得我是两种技能都有一些的,这也让我能对这个项目有一个更全面的认识。但是同时软件工程对我来说确实有一些吃力。我很高兴这个项目开源后我在这个方面得到了许多人的帮助。我和一些软件工程师们合作过。

他们很喜欢代码上的难题,也喜欢实现各种复杂的东西。但是对于我来说还是简单的 for 循环最好用。我也不太相信 JavaScript 引擎,所以我尽量让逻辑更直接一些。但是如果是着色程序或者物理计算之类的复杂数学,我理解起来会有些吃力。如果需要用到的话,我是能搞清楚的,但是问题解决完后就会马上忘掉了。

我确实不是什么数学天才,也不是什么土木工程专业的人,我更多的是在即学即用。但是这确实很辛苦,特别是当你在创造这么大且功能这么多的一个项目的时候。比如需要学习如何进行代码测试、持续集成。

这个整合集成就是要尽可能确保一切都能够合理安排。要意识到别人是依靠你的,你不想去破坏别人所做的努力。因此,你要去学习所有的事情或工作(可能对我来说其实并不觉得有趣)。同时你也要做一些社区管理的事情,要保证社区里的人是相互尊重的,也要意识到社区里可能会有人可能不圆滑,不擅长沟通,甚至发生口角。这个时候你要思考原因和想办法,也要去确保在这种情况下人们也是能够一起工作的。这有点像经营一个公司,要确保有一个好的社区文化。

主持人: 我觉得用团队合作来形容你们是比较合适的了。你们都有不同的背景,也有不同的思考问题的角度。

Ricardo@mrdoob: 一个团队的话,你是可以预期每一个人每天都会来上班。但是这边会今天来一个人,然后过两天就离开了。你很难知道应该把自己的时间花在谁身上。可能某个人能为项目贡献一个东西,但是却不太会与人交流。这时你就需要选择是否要花时间与他沟通。如果花时间了他或许可以更好地在项目中合作;但同时他也可能过两天就消失了,花在他身上的时间就得不到什么回报了。

同时也会用一些人一直在项目里活跃,持续贡献了 6、7 年可能的人都有。我很高兴他们喜欢这个项目,也很高兴他们愿意来帮忙。这种合作方式整体上是有好有坏了。最终会有一些人一直留下来,这部分人确实有点像一个团队。我可能不是最好的管理者吧。

主持人: 你如何让自己跟上最新的技术发展?

Ricardo@mrdoob: 嗯,一般是通过推特。到最后你总会关注该关注的那些人。只要有人开始用新技术之类的,他们就会转发这些新技术。

同时我也会参加一个叫 SIGGRAPH[6] 的会议。在美国和亚洲也有不同的图形处理与编程相关的会议。但是他们的议题对于 Web 的能力来说一般都过分超前了。比如说,这些会议会讨论新的 PlayStation 或者新的 XBox 或者最新电脑上能做什么,但是在 Web 上开发我们做的东西必须能在任何地方都能运行。比如你能支持的最慢的手机,比如我母亲用的手机。因此你无法使用最新的技术发展,因为那些东西一般是面向最新的 PlayStation 之类的设备的。于是我们一般用的技术相比最新发展会晚 5 年左右。这样的的好处是你并不需要紧跟最尖端的技术发展。我可以坐着等 5 年,然后看看那时候有哪些技术还在被人们讨论,并挑这些比较稳定的技术来实现。总而言之是通过推特来了解最新技术发展,然后不让自己因为无法使用最新技术而沮丧。

主持人: 听起来很有趣的样子呢。好的,下一个问题是:“协调好工作和私生活永远都不是一个简单的事儿” -- 这我们都知道 -- “那么你平时是如何协调好自己的工作、开源项目、和私生活的呢?”

Ricardo@mrdoob: 真的不太好,但是比起五年前好多了。最终我成为了谷歌雇员,然后我正在做的事情就像你看到的那样。

从某种意义上讲,这个项目从一开始就是全职工作了。我做这个项目能得到报酬,但是很难找到一个公司满意我做的项目、信任我做的事情、并且愿意为我提供薪资、职位。

直到今年初吧,前十年一直很难知道这个项目作为职业是否足够稳定;我能不能继续投入这个项目;我应不应该寻找其它方案。这一切给人的压力是很大的,也让人很难去做其他事情。所以直到今年我的情况才有所好转。我在这个中心工作了,也有了可以一起出去社交的好友。但是前些年总体上说是非常艰难的。特别是去年在推特上有讨论说希望能把一个 Github Repo 设置成休假状态。因为当你在为一个公司工作的时候,人都会有休假,都有相关政策。但是当你做开源项目时别人是无法知道的。比如当别人提交一些代码的时候就会有预期,期待你会在一天内 review 一下,或者完成 merge ,或者至少给一些反馈。

而当你没有消息时他们就会觉得这个项目是不是出了什么问题。也不知道为什么,人们对开源项目就有这种预期,期待应该总能立马得到答复。我觉得 Github 还可以再做一些改善这种情况的工作,让我们能有更多的喘息空间。相比正常工作来说,这是让开源项目更艰苦的原因之一。(如果不能接受这样无休的状态), 我真的不太推荐做开源项目。

真的很难说“这个星期我要做别的事情”。现在情况好多了,但是最开始的 10 年我一共就休了一个星期的假,原因还是当时断网了。我觉得应该不是所有开源项目是这样的,但是 Three.js 成了这个样子。乍眼看去似乎没有多少,但当你细看时会发现代码库和工作量都很大。但是我依然觉得这是一件值得做的事情。

有一件事情对我的帮助很大。三年前,我开始做表格来记录我当天有多少个 issue 、有多少个 PR 、有多少个通知。这样你就能看到统计数据,看到 PR 数量减少、issues 数量减少、通知的数量减少。在这之前这些数据我都不知道。当时就像你的电子邮箱里不停地收到新邮件。假设每天有十封新邮件,但你没能在一天内处理完,明天又多十封,后天再多十封信。

所以你需要知道自己每天必须解决多少事件才能让这些数字稳定下来。对 Github 来说也是同样的,每天都有数不完的通知。当我把这些数据可视化后,就比较容易看出我需要做多少工作,或者是否需要花一周专注解决并减少 issue 。这三年以来,我们过去有 700 多个 open issues,现在减少到了 300 多个。

这件事的帮助真的很大。一般的大公司处理这种问题是自动关掉一年未更新的 issue 。他们就自动关闭了,只是说如果还有问题,欢迎你再开一个 issue 。我不太喜欢这种做法,现在我是尽量不使用这种处理方法。

但是那( issue 统计)确实有帮助。把数据可视化后你至少能看到它。如果你看不到的话,就只会感到压力越来越大。统计帮了我很大的忙。

但是值得一提的是,至少我不知道有任何学校会专门教你这些处理事务的方法。你只能自己探索并学会如何处理这类事物。没有任何“开源项目管理者”学院或职业,你只是开始做了之后需要自己搭建这些系统。好的地方是因为这都是开源的,你可以看到其他人采用的方法。这会有一些帮助,但我们也只能一点一点地互相学习。

主持人: WebGL 和 WebGPU 的对比,如果要投入学习的话应该选择哪一个? 如果想学习 VR 是不是要学 Unity ?

Ricardo@mrdoob: 我认为要视情况而定吧。如果是现在开始学的话可能两个都学一下会好一些。如果是 5 年后学的话可以忽略 WebGL 了。嗯,差不多两年吧,如果两年后开始学的话就直接忽略 WebGL,去学 WebGPU 吧。我先岔开一下话题。主要是,OpenGL 已经有 20 年历史了,而 WebGL 也有 10 年历史了。相对应的,这些 API 与硬件的交互方式等,都是为那个年代的硬件而设计的。所以才会有 WebGPU 这样的新 API 。它能更好地与现代 GPU 做交互。

对于一个新手来说,WebGPU 可能会更难上手。但我同时认为要了解 WebGPU 所需要学习的东西也更少。并且主要的优点是 WebGPU 更适合我们现在使用的硬件。它会降低 CPU 承受的负荷。总的来说,WebGPU 优化得更好。它更简易、更直接,但是它的一些概念会更难理解。不过它确实优化得更好,并且也应该会让系统更稳定。所以说,如果是今天就开始学,两个都可以学一学。

从 WebGL 开始学,然后也看看 WebGPU,因为趋势是向 WebGPU 发展的。运气好的话,两年后开始的人就可以直接跳过 WebGL 了。现在 WebGPU 还没有在浏览器中普及。你必须配置几个 flag 才能开启这功能。但是再过一两年,这个技术会逐渐普及稳定,那时候我们就可以抛弃 WebGL 了。

主持人: 那我如果想学习 VR 的话,是否需要学习 Unity ?

Ricardo@mrdoob: 嗯,我觉得这还是取决于你想要达到什么目的。我认为 WebXR 也挺好的。Unity 会给你一整套可视化的工具。你甚至可以在不怎么写代码的情况下实现很多东西。对于 Web 来说,我们有 WebXR ,这让我们也可以做 VR 和 AR 。但是我们没有 Unity 那样的工具。

所以还是取决于你的意图。如果你想快速做点东西出来,可能还是用 Unity 会更简单一些。但是用 Web 的好处是:如果你做点什么,像我们十年前用 WebGL 做的 demo 那样,它们的网页如今都还能正常运行。这个特性并不是那么常见的。Windows 的 Native 应用可能会这样,但是如果你用 Unity,或者 iOS ,或者 Andriod 的话,每次发新版本你可能需要重新编译一下程序。所以最后还是取决于你的目的是什么。但是我们现在有了 WebXR ,我对未来几个月发展出相关工具是抱有希望的。

多尝试点东西肯定是好的。但同时 VR 不是必须二选一的技术。你可以两个都学。VR 不像 WebGL 那样错综复杂深不可测,需要花费大量精力去研究。VR 的话,你可以多学点东西。

我们之前好像已经讲过一点这方面的事情了。它更多的是一个我需要的东西。我最开始只是在 JavaScript 里做些实验,最终发展成想尝试一些 3D 实验,我自然就有了这样的需求。其实这个库是我在做 Flash 时候就开始做了的,后面我把它迁移到 JavaScript 里了。我当时是想要有一个适合自己做事风格的引擎。

对我有帮助的是,从某种意义上讲,我依然是为了自己而开发的这个库,只是如今我已经没有时间自己使用它了。很高兴它能对很多人产生价值也能满足很多人的需求。但是开发之初确实只是因为自己的实验需求。

主持人: 你是否有打算启动一个 JavaScript 的 Three.js 的组件库项目?比如 react three fiber

Ricardo@mrdoob: 不不,我觉得总有一个该停下的地方。一般做这些库的一大难题是选择你的范围,也就是你想解决的到底是什么问题。我认为我们选择的范围已经在解决很广泛的一类问题了。我们不只是提供快速渲染的能力,我们还加载各种常见的文件格式,并且对其进行解析。

这里要重申一遍我并不是一个软件工程师,所以对我来说配置好组件库环境、保证所有东西正常运作、保证 API 足够稳定都是些辛苦的事情。你总是需要在某个地方划定范围的,我可以在这之内做好工作保证库有充分的能力。然后希望其他人能在此之上创造组件库。

我们是可以花时间清理我们的范例,让他们更像组件。但是我们同时还有非常多其他需要处理的事情。

主持人: 现在我们已经有了一个很好的 WebGL 库,我们是否需要花一些时间在学习低层次的技术上面?比如计算机图形学?

Ricardo@mrdoob: 不一定必要吧。就像我学 Flash 那样,你迟早会遇到问题。然后为了了解为什么出问题你就需要去了解底层发生了些什么。然后你就会一层一层地挖掘,直至你对整个系统有更深的认识。当然有一些人是需要学习了基础后再向上学。但是我的话是那种平常学习我所需要用到的知识,然后如果需要深挖的时候再进一步学习。所以如果有人学 WebGL 三年都没有遇到什么问题那也挺好的,不需要去了解底层机制可以直接跳过。这个框架本来就是让大家不需要重新造轮子,而是专注于更好的内容创造,专注于表达自我。但是如果有人想学的话那当然可以,这都取决于他想做什么。

计算机,你是永远学不完的。我们现在在讲 WebGL ,但是 WebGL 底下还有驱动器,驱动器底下还有处理器和其他硬件,根本学不完。而且深入学习 WebGL 底层原理也不一定会让你更有效率。

主持人: 对于那些有志于学习图形编程的人,有没有什么技巧让他们作为初学者来学习呢?

Ricardo@mrdoob: 最后还是要学习着色器等,我可能要订正我之前的回复了。可能还是要看一点 WebGPU 。他们需要意识到这个领域的复杂程度。我最开始时候以为 Three.js 只会做 2 年的样子,但是现在做了 11 年了且还在继续。这方面我真的没有什么建议。

对我来说,相比为了学习而学习,我的学习更多是为了某个目的而学习。比如说为了做一个音乐视频,又或是为了做一个游戏而学习相关技术。最后你完成了一个项目,也同时在完成项目的过程中学到了东西。而不是“哦,我会让方块打转”,或是“我会移动镜头了”。会这些又怎么样呢?当然这也因人而异,但对我来说,在实际项目中学习更适合我。

主持人: 所以你学习物理和数学只是想学而已?

Ricardo@mrdoob: 对我来说,绝对不是“嗯,我特别想学物理了”,而是“哦,我必须学习物理”

主持人: 那么数学呢?因为数学是图形编程必不可少的部分,你对此有什么建议?虽然你可能不喜欢这个学科。

Ricardo@mrdoob: 我一定要学的时候当然会学,但是我很幸运的是,因为这是开源项目,你会吸引到一些非常喜爱数学的人。他们会花时间在物理相关代码,也会花时间研究相关的数学,保证计算得准确又完美。所以我不需要自己去做。但是如果有必要的话,我是会去学的。

主持人: 所以可能因人而异,选择适合自己的方式就好。那么想请问你怎么看 Babylon.js[7]

Ricardo@mrdoob: 有不同的选择固然是一件好事。我们也会关注彼此的解决方案,因为在某种程度上讲,我们想要解决相似的问题。只是我们有不同的方案。他们的方案更关注于游戏开发,也因此吸引了更多想做游戏开发的人。而我的项目更多的是一个 Flash 的替代品。所以会更适用于各种需要动效的广告。也因此我们的着重点在于尽可能地降低框架的文件大小。

Babylon 更多的还是专注于解决游戏设计问题与相关工具的开发。但是我们想要实现相同的功能的时候就会看一看对方的代码是怎么实现的。在浏览器中开发总会遇到问题,这时就会很好奇对方是怎么绕过这个问题的。在这个方面,我们会帮助对方节省时间。也会有的时候会觉得对方的代码不太好,或者会引起什么问题。那刚好,你可以在你那边解决一下。所以开源库当然是越多越好。相比于只能用第三方私有工具,拥有这么多选择好多了。

主持人:是的,确实好多了。可能它可以给你提供一个不同的视角,解决不同问题的不同方式,所以从用户视角看,他们更像是一个给用户更好的选项?

Ricardo@mrdoob: 最近我们也会有到一些问题。当我们在其他网页上看到 3D 动效时很难区分它们用的到底是哪个引擎。想搞清楚的话,要安装个浏览器插件,然后在看着色器,总之是很麻烦的。然后我就想是不是可以给 canvas 加一个 attribute 来标注这个信息。上个月我就和 Babylon 和 Play Canvas 的人商量了一下然后很快达成了一致。现在就可以直接从 HTML 里看出是用的 Three.js 还是别的引擎了。所以我们也是很关心对方的,也会对彼此的痛点感同身受。所以自然就会有互相帮助了。

主持人: 这非常好呀,合作大于竞争了。那么你认为哪一个对那些最近刚开始的人来说更适合初学者?

Ricardo@mrdoob: 说实话我没怎么用 Babylon 做过什么项目,还有 PlayCanvas 。PlayCanvas 可以可视化的操作,提供一个编辑器,不写代码的情况下,在编辑器上做更多的事情,可能更适合(初学者)。我也不太清楚怎么选择,每个人都不太一样,还是要看它们自己更适合哪一个。

主持人: 请问对 Google 推出的 filament[8] 渲染引擎有什么看法?

Ricardo@mrdoob: 那又是另一个拥有特定使用场景的框架。这个框架没有试图让事情变得更简单,而是转为谷歌项目的需求而做的。把你搜到的东西,例如小动物之类的,放到你当前(摄像头)的空间里(渲染出来)。这个代码也是被开源了的,这是个好事,因为它们这代码能让东西看起来很逼真。但是这更多是为 native 应用设计的,不是特别适合用在 JavaScript 里。但是作为一个可供选择的选项是一件好事。入门学这个的话可能会比较艰难,因为它不是为此而设计的。

主持人: 关于 Three.js 内存释放,总是释放不干净,有没有彻底释放内存的方法?

Ricardo@mrdoob: 这就要回到我的工作了,要看看人们遇到了哪些问题,然后做一些能解决这些问题的东西。现在的话,当你在场景中创建 3D 对象、相机、材质的时候,这些对象都可以 dispose ,这个方法会清理掉所有相关的内存。但是这样你还是需要记录自己创建的所有东西并且自己 dispose 掉。我在考虑做一个自动清理一个 scene 里所有资源的方案,这就是我之后要做的工作了。我会尝试落实这个方案,这样其他人就不需要自己做资源清理了。这件事情的优先级很高。

但是当你看到有人遇到问题的时候,我们是可以解决它,但是应该如何处理,并且处理得让所有人都认为是合理的。所以确实很难覆盖到所有的使用情景。但是在这个例子中,确实是我们应该做的事情。

主持人: 当渲染的数据很多的时候,比如全市的建筑,如果既保证渲染的质量,又保证性能,不出现卡顿等问题?

Ricardo@mrdoob: 能渲染的东西是有上限的。如果你想在所有电脑上都能跑的话,你不能预期它能渲染五百万个三角形。但是对于一栋楼,或者说重复数量很高的东西。如果所有的列都长得一样的话,我们不需要分开来渲染。有一个叫 instance mesh 的东西,用这个你可以告诉 GPU 把某个形状在某些位置上渲染 1000 遍。所以你只需要上传一份资源到 GPU ,然后告诉 GPU 去在 1000 个不同位置上渲染。这就是被叫做 GPU instancing(GPU 实例化[9]) 的功能,我们也有支持这个功能的 API 。你需要尽可能地利用这个功能。每当有形状被重复时,你都应该去用。然后就要看 GPU 实际能够渲染多少东西了。这样的话瓶颈就不是库了,而是硬件本身。

主持人: 类似的问题,刚刚我们讨论了有大量物体的情况,那么光源呢?光照计算在渲染过程也占了很大的比重,有很多光源的时候,Three.js 要怎样优化呢?发生过度曝光的时候又该怎么办呢?

Ricardo@mrdoob: 嗯,我不是很清楚这个问题想表达什么,但是有一个和这个有关的问题。我们不能有无限的光源。每当你往 scene 里加一个光源,你可以理解为你在渲染这个 scene。你加多少个光源就会渲染多少次。比如说如果你加了 5 个光源,就会把这个 scene 渲染 5 次。不尽然,但类似这样。

某种意义上可以这样理解,虽然不完全准确。但是如果你有 5 个光源,那就意味着每一个 material 都需要考虑到 5 个光源的作用效果。最终渲染的时候就会变得 5 倍复杂。如果光源本身位置不变的话,一般可以使用 blender 等工具把灯光的效果渲染到 texture 里。这样就不会有实际的动态光效。通常 scene 里加光源是为了让它们移动,或者只加一两个。但是如果需要更复杂的东西的话,一般最好还是把灯光效果 bake (烘培)进 texture 里。这样的话渲染就会变得很快了。然后剩余的有需求的地方可以用动态光源渲染。

我觉得这个问题指的是这件事儿。只是曝光的话不会让东西运行得更慢。但是如果问题是过度曝光的话,渲染器有一个曝光参数可以调节,就像照相机那样把灯光调暗。

所以,根据情况而定。问题稍微有点模棱两可。所以如果是光源太多,那就做一些 baking。如果是光源太强,那就调整一下曝光的参数。

主持人: 我想在真实世界中,可能有不同的光源,比如自然光或者人造光。当有许多类似这样的光源的时候,它们(和现实世界中的处理方法)一样吗?

Ricardo@mrdoob: 我们没有办法做到和现实生活中那样的,太阳光会不停地反射,直到整个房间都充满光。现实生活中一个房间采光非常好,但光源只是从太阳这一个点发射出来的。

但这对计算机来说运算量太大了,所以我们是无法这样做的。所以特别是光照这种东西,我们需要做非常多 hack ,让效果看起来还能接受。我们计算速度没有现实那么快。

主持人: WebGL 在手机移动端、PC 网页端、VR App 端,分别都有怎样的性能表现/差距?以及是否有什么能力限制的差异?

Ricardo@mrdoob: 能在所有环境下都运行是一件好事,但能在所有环境下都运行也是坏事。因为它必须在所有环境里都能快速运行。你需要关注的东西也要更多。

我的电脑一般都不会太快。我有一个 2016 年的 MacBook ,用的是集成显卡。所以如果一个东西能在我的笔记本上运行,那它应该就能在大多数其他设备上运行了。关键就是不要在一个特别强大的计算机上工作,不然它可能就只能在你的机器上运行了。

现在我不这样做了,但是我以前会买一些老手机,比如如果印度有一个 $90 的手机,我就会想办法搞到手。我们做东西的时候我就会尝试在这些设备上运行。这就是做移动设备方向的项目时会遇到的问题。但是对 VR 来说,好的地方是,当你支持 VR 的时候,一般你是专门针对 VR 这一个使用情景的。毕竟要做到同时支持 VR 和非 VR 体验是很困难的。

所以如果做 VR 的话,应该可以比较自信地判断最低配置会是一个 Oculus Quest 之类的设备。至少你可以忽略那些手机。性能的话也是只需要在 Quest 上测试一下。但是如果你要针对移动端的话,就需要支持那些了。也看具体项目,以及你的受众。但是你需要找到要支持的最低配置。

主持人: 这听起来好像是当你面向不同设备进行支持的时候遇到的不同的问题?

Ricardo@mrdoob: 还有一件事,用 Three.js 的一大优势是一些手机有自己的问题,所以我们需要为这些手机找到解决方法。以至于平时人们都不会发现,只觉得它在所有地方都能运行。但不是它真的能在所有地方运行,只是像 Three.js 和 Babylon 这样的库让它感觉上像是能在所有地方运行。但总会有些小问题,比如一些三星手机没有某些功能,你就需要改变成能用的其他写法。但是这个库的初衷也是为了让别人不需要关心这些细节。直接拿去做点项目创造点东西。

主持人: Three.js 大概是从什么时候开始关注性能优化问题的?以及你认为目前为止做出的最重要的三个性能优化点是什么?

Ricardo@mrdoob: 对于性能优化来说,我认为你是没办法在项目设计之初就保证的。你只能尽可能地保证项目的性能。但当时我也没有太多 WebGL 的相关经验。所以两年前我还得删除一些生成 geometry 的代码。因为对于性能来说那部分设计的并不好。用户生成 geometry 倒是很方便,但是确实性能不太好。所以我们必须把他去掉,即使这意味着对用户来说没有那么方便了。某种意义上讲,你的设计决定会让所有人的电脑做更多的工作。我们从第一天开始就在做优化。也有一些 contributor 乐于翻阅代码库来寻找可以实现性能优化的地方。

这个月,一个叫 Gero3[10] 的 contributor ,在翻阅各种渲染器相关的代码。比如说对数组的使用。假设你有一个球体,且想用某种特定光照把它渲染成红色。那么你就需要有一个拥有红色的的 material 。如果你有 50 个这样的球体,那就有 50 个红色的 material 。为了在 GPU 那里渲染这些 material ,你需要为它们创建一个 shader 。

但是那些 material 都是红色的,所以按理说你不应该需要创建 50 个独立的 shader ,因为它们就是同一个 shader 。所以每当我们渲染的时候都需要做相关检查,每一帧我们都会检查是否已经存在有相同的红色 shader ,并决定是否需要重新编译一遍。因为 GPU 并不想创建 50 个这样的 shader ,创建一个就够了。所以每一帧都运行这个判断相同 shader 是否存在的逻辑对 CPU 来说是非常大的消耗。这就是上面说的 Gero3 正在优化的东西,让它变得更快一点。我们有一个测试会渲染 2000 个相同的球体,然后看看能不能把用时降低 5ms 。我们有很多像这样的例子,想了解更多的话,可以看看我们的 Commit 页面,看看最近的 PR 就能看到这里有个性能优化,那里又有个优化。当然还有不少代码清理工作,比如去除一些用户不应该需要关心的内容。

现在是还有一些为 material 类型做的数学计算。比如说最近我们在做的一个 material 可以渲染出杯子里的说折射光的效果。要实现这类效果的话是需要很多数学的。这是无可避免的。

主持人: 做 3D 渲染的时候,CSR 和 SSR 的优缺点是啥?

Ricardo@mrdoob: 这个问题应该是指 React、Vue、Modern Web Application 之类的支持服务端渲染的概念吧。

但是对实时 WebGL 3D 来说,是没有这种东西的。不管怎么样,你永远是在前端渲染所有东西。完全没有任何好处。比如说 Three.js 是 100KB ,你自己的代码可能 10KB 。如果你在服务器渲染,得出的可能是一个 4MB 的图片。所以把代码送去前端,在前端完成渲染是更容易的,发送的数据量也小很多。但是如果说的是云渲染,比如说 Stadia ,还有 NVIDIA 那种用户想玩游戏但是没有合适的硬件,那这种是挺好的服务。因为这样你是在云端渲染,就不用关心用户的硬件是什么样的。但是这也就只有谷歌这样的公司能负担得起这种服务了。对于 Web 来说,一般只是在前端。

主持人: Three.js 什么时候会采用语义化版本控制 ?现在的方式在升级时不能直观确定兼容性?

Ricardo@mrdoob: 嗯,还需要一些时间。Semantic Versioning 是在给其他开发这一种承诺,承诺当前代码是稳定的,且之后不会随意改变。这种做法到最后可能会导致你必须维护 3 、 4 套历史代码。这对于小一些的项目会更容易做,但对于 Three.js 来说维护一套代码就已经很吃力了。我们做事的方式可能会给其他开发者带来一些麻烦,但是我们可以持续优化我们手上的东西。如果这个月把什么搞坏了,下个月可能就修好了。但这样你真的需要使用最新版本。这么做确实不太寻常,但是如果我们做了 Semantic Versioning ,我可能早就不再热衷于这个项目了。所以这是让我选择继续做这个项目,还是让其他开发者们日子好过一些。

依然有很多事情在发生。也有很多东西在改变。很难说哪些部分已经稳定了,以后都不会再改动了。这个也是,我们 5 年后再看看吧。

主持人: Three.js 中部分源码放在了 example 中,被评论代码结构不规范,这个是出于什么考虑?会改变吗?

Ricardo@mrdoob: 嗯,这种东西是很难设计出一个体系然后说就是应该这样操作的。可能刚开始设计的时候没有考虑到一些使用情景。后面就需要做一些修改。积累到一定程度后,可能就干脆从头再做一遍。这就是一个迭代的过程了。那些示例代码 10 年前比较说得通,因为那时还没有 Npm 。所以你可以下载来然后有地方起手。但是现在有了 Npm 后人们就开始从 Npm 引入了。人们就想复用这些代码。但是这是完全不同的开发流程。

这就有点 Npm 把某种开发模式强加于我们的感觉了。也许解决办法等某个 example 稳定了以后,就把它抽出来放到一个 addons 文件夹里。但是你不会希望随意这么做。你必须确定这是你的最终设计。我也知道,这也不是常见的处理方法。

主持人: 如何优雅地 modify 内置的 Material (不看源码的情况下)?

Ricardo@mrdoob: 现在的版本不可以。但是 sunag 正在开发 material 节点功能。那样就会像 blender 里一样做节点之间的连接操作。当然你也可以从代码里面修改它。整体上是和我们现在的 mateiral 很相似,但你可以修改它们之间的顺序了。

这是我们正在做的事情,但当前是没有办法做到的。希望明年我们能把 material 节点的编辑器也做好。然后就可以尝试用 material 节点取代过去的系统。

我们同时也在为 WebGPU 渲染器做开发。这个渲染器就只会使用 material 节点了。但是现在的代码就只能用已有的 material 系统了,所以没有什么特别好的修改内部 material 的方法。

主持人: 看到 Three.js 的 WebGLDeferredRenderer 被移除了,请问后面有计划支持一下延迟渲染( deferred render )么?

Ricardo@mrdoob: 目前没有这个计划。也是和之前相同的问题,维护一个渲染器就已经够费力气了,更别提同时维护两个用不同方法实现的渲染器了。但是我们有一些 WebGL 工具了,如果有人想做的话,已经有其他更好的解决方法了。Deffered Renderer 最大的优点是相比现在的渲染器,它能让你使用更多光源。但这同时也会带来一些它自身的已知问题。所以这主要还是我们对这个生态未来走向的一个判断,所以目前是没有把 Deffered Renderer 带回来的计划。

主持人: 处理和解析 OBJ 和 glTF 模型,是否花了你很多时间学习和开发?

Ricardo@mrdoob: 是说加载文件的代码吧。OBJ 文件格式其实挺有意思的。它乍眼看去好像非常简单,但是你真的去加载它的时候却又无比复杂。你可能会以为一个下午能搞定解析这文件的代码,但是做的时候就会发现很多问题,比如“需要加载其他文件该怎么处理”之类的。你很难摸清这个文件格式。特别是因为 OBJ 文件应该是在 GPU 出现之前就设计的文件格式,所以现在处理起来很麻烦。

glTF 是一个较新的文件格式,但它也在不断进化迭代,不断地有新功能被加入进去。其实我们给引擎增加的一些新功能也主要是为了能渲染 glTF 文件格式的新特性。glTF 不断地逼迫我们研发新功能。我很幸运 Three.js 项目里有一些人主动负责维护和迭代这一部分代码。解析文件的确是项目中很消耗时间的一个环节。

glTF 有一个固定的标准,有一组人专门制定这个标准。但是 OBJ 文件格式就有点不同的人添加的不同的功能的味道了,整体标准比较混乱。有的时候你会找到写法不同的文件。加载文件都是自己独立的一个小项目了。

主持人: 听起来有些复杂。在这个过程中,有什么是你希望自己之前就学到的?

Ricardo@mrdoob: 很好的问题,应该是项目管理吧。像之前说的那样通过做表格来记录进度之类的。又比如说我最近开始使用的一个叫 notion 的 App 。你可以在那里记录你的新想法。它更像一个 wiki ,比 Todo List 要好用很多。有许多这种大家在用的技巧,要是当初开始的时候我就用上了的话该多好。

各种各样的点子的想法就像一个树一样错综复杂。没有人能把它们全部记在脑子里。你需要把他们总结、归类。之前我一直没有找到帮我做这事情的合适的工具。现在用 notion 即使没法帮我做太多事情,它至少能帮我做好记录,确保我不会忘记任何点子。

主持人: 在开发 Three.js 时,如何平衡包体积、性能、功能集合、 API 设计、使用 Three.js 的开发体验等因素?

Ricardo@mrdoob: 嗯,这就是我的工作了。文件大小也是我十分重视的一部分。在过去的 2 、 3 年内,我们的压缩后文件大小基本稳定在 150KB 左右。有时多 0.1KB ,有时少 0.1KB 。我很关注这一点,也不想让 Three.js 变得过于膨胀了。这也直接影响了我决定什么能加到库里,什么不应该加进去。

有的时候如果想增加新功能就必须把别的东西去除掉。我们会看有没有哪部分代码用的人比较少,然后索性把它搬到 examples 文件夹里去。也不知道怎么的,这个 150KB 的文件大小成了我们衡量项目范围的一个参考。

性能也是属于日常工作之一。有很多人一起看代码一起留意性能优化对此有很大帮助。开发者体验,这个还是需要自己亲自体验。虽然我最近做这的机会也不是很多了,但是你必须去使用自己做的东西。只有这样你才能真的体验到什么地方好用,什么地方有痛点。你必须能和其他开发者产生共鸣。可能会有开发者不太擅长交流,那你可能就无法理解框架到底哪里不好用。但是只有自己去尝试去体验了以后,才会真正的体会到他们的感受,才会明白那个东西的确需要有人去修复。为了提升开发者体验,你必须去使用自己做的东西。

主持人: Web 端在 VR 领域有什么机会吗?

Ricardo@mrdoob: 现在可能没有那么明显,因为现在大家差不多都去开发 Oculus Quest 和 Quest 2 了。但是 VR 早期的时候虽然有多个不同的设备,但是因为可以只写一个 Web 的 VR 应用就能适配,所以还是挺不错的。

现在的话你支持一下 Quest 就可以了,其他设备用 Unity 也可以解决。但是我认为未来迟早会有更多 VR 设备出现的。这就会让 Web 这种能在所有设备上运行的特点变得很有用了。并且做 Oculus 浏览器的人们,他们是非常支持想创造 VR 内容的 Web 开发者的。我认为现在是一个非常适合探索这个方向的时机,现在这方向上也有很多东西有待创造。比如创造相关内容所需要的生产工具。

在电脑上我们受限于触摸板、鼠标等。网页上我们也基本上只是用一个光标点来点去。但是在 VR 里你可以直接抓住物体,可以推物体,可以直接操作它们。这是一种全新的交互方式,相应的也需要有人创造新的设计模式。估计 Apple 现在就已经着手设计这些新交互模式了。当然 Oculus 也同样在做这些事情。如果我是现在开始从头做一个项目的话,我应该也会选择这个方向。因为这里还有很多东还有待发明。但是这需要你花多个周末尝试不同的东西,然后可能就会设计出一些有用的东西。我真希望我能有时间亲自做这些事情。

主持人: 所以为了适应新的趋势,在当前的背景下,是否有机会开发 WebGPU ?

Ricardo@mrdoob: 我们现在正在开发 WebGPU 的渲染器,而且浏览器也逐渐开始实现 WebXR 、 WebGPU 了。现在也才开始,但是我们正在努力研发 Three.js 的 WebGPU 渲染器以及支持在 WebGPU 上跑 WebXR 。这可能还需要花一年的时间吧。

主持人: Three.js 在 WebAR 方面有什么重大影响或者推动作用吗?

Ricardo@mrdoob: 可以这么说吧。我觉得可能会有企业会在 Three.js 的基础上开发工具链来创造 AR/VR 内容。他们应该不会想自己为这个项目亲自写一个渲染器,所以估计就会用 Three.js 来满足这个需求。我也会尽量出一些 AR 或者 hit test 的示例代码。但这就像 react-three-fiber 一样,我还是希望会有其他人出来创造一个解决这问题的库。

主持人: 看到你在 Twitter 上说 “Web3 is the web after three.js, obviously”请问你如何看待 Web3 ?

Ricardo@mrdoob: 那个主要还是在开玩笑了,因为所有人都在尝试给 Web3 下定义。然后刚好 Web3 ,Three.js ,都有 3 嘛。主要还是开个玩笑。我认为 Web3 应该是互联网数据是以区块链的形式存在的时候的样子吧。一个例子,就像是这些 NFT 交易网站。其中有一个,虽然他的维护者决定关闭网站,但是由于数据都是以区块链的形式存储的,其他人就可以再做一个网站,并且重新恢复了这些数据。对我来说的话,这就是 Web3 ,会有很多使用同一个数据库的网站。你可以为相同的数据创造不同的前端。但是这个推特主要还是为了开个玩笑,因为很多这种网站的前端就是用 Three.js 做的。

现在 Web3 是什么可能会更清晰一些了,到时候我可能就把那推特删了重新说点别的什么吧

主持人: 元宇宙和云计算的关系(技术方面)?

Ricardo@mrdoob: 对我来说,元宇宙更多的像是一个操作系统,只是这个操作系统不再存在于你眼前的屏幕中,而是你存在于这个操作系统之中。我觉得 Oculus Quest 就是一个很好的例子,当你带上设备后,你的所有的窗口都围绕着你,你也可以从那里打开应用。所谓的元宇宙似乎就是指你在这种操作系统中邀请你的朋友来访。

我觉得,我们还是从习惯操作系统环绕自身开始吧,习惯这样的交互,然后之后的情况之后再看吧。关于云计算的部分以后总会需要一个处理这些连接的地方。你自己的设备上肯定无法处理你和你朋友相关的所有信息。那时候就会需要有云服务来协调这些事物。

那时候你知道带上来 VR 设备,你的朋友就会出现在你身边。但实际上只是云服务在告诉你应该看到什么。

总之,这就是我对元宇宙的理解。

主持人: 在元宇宙概念大热的今天,如何看待 WebGL 、图形学的发展趋势?目前是否处于技术大变革的前夜?泛前端技术人员应该在哪些领域耕耘?

Ricardo@mrdoob: 如果你仔细想一想的话,现在的互联网全部是建立在 HTML 文件和 HTML 标准之上的。你访问的每一个网站都会产出相应的 HTML 文件。所有的东西最终用的都是 HTML 。如果我们把元宇宙想象成一个空间化了的互联网,那么我们就会需要一个跨平台的、所有人都看得懂的语言。所以我们需要定义出一个这些 VR 设备都能看得懂的通用语言。而根据历史发展来看,依靠单独一家公司来设计一套适用于所有设备的语言一般是行不通的。以 HTML 为例,它就是一个开放标准,任何人都可以使用它,也可以去渲染它。所以如果元宇宙能建立在类似这样的开放标准之上的话,那我认为 Web 上的一些技术,如 WebGL ,就会变得非常适合元宇宙了 -- 这是我的一些认识。但是如果有人能够创造一个足够有吸引力的世界,或许他的这种私有方案也能成功。也许像 Meta 这样的大公司能做到。关注元宇宙当然是好事,但是我也不清楚今后的具体发展会是什么样子的,因为整个元宇宙的概念过于抽象了。但是感觉上 Web 的一些技术和思路是可以复用到元宇宙上并解决一些相关问题的。我们一起拭目以待吧。

主持人: 是呀,我们很难知道未来会怎样。

Ricardo@mrdoob: 是啊,十年前我也根本想象不到我的代码如今被他人如何使用。

主持人: 如何定义元宇宙与 Three.js 的关系?你觉得 Three.js 未来的应用场景可以切合元宇宙吗?

Ricardo@mrdoob: 我也不是很清楚。直觉告诉我 Three.js 可能会很适合元宇宙,但如果是这样的话,它会成为一个非常重的责任,也会让我感到些许害怕。完全是天上掉下的重担。

嗯,我们一起期待吧。我能想象到它会很适合元宇宙。虽然责任会很大,但是同时我为我能帮助到其他人而感到欣慰,也很乐于倾听别人都遇到了哪些痛点。如果到时候可以适配到元宇宙中的话,我希望那时能有更多人帮我一起做这方面的研发,从而成为对社区更有帮助的人。我认为会很匹配的,但是同时也会有一些害怕。

---全文完---

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值