Three.js是什么?

0 股票
0
0
0
0

介绍

Three.js 的功能非常强大,它与其他 3D 领域的关联性有时令人困惑。它的应用范围也在不断发展,因此很难概括,而且这些观察结果也带有主观性。.

JavaScript 3D 库

该项目的目标是创建一个轻量级、易于使用的3D库。该库提供渲染功能。 , CSS3D 和 WebGL。.

这是来自 GitHub 代码库的官方描述。它确实概括得相当不错,但这句话中的每个主题本身都是一个很大的话题,而 three.js 的功能远不止于此。.

这个库本身是用 JavaScript 编写的,旨在用于 JavaScript 环境。在大多数情况下,这意味着它运行在客户端——也就是某些设备上的 Web 浏览器中。但借助 Node.js 和无头浏览器,它也可以在服务器端使用。人们首先想到的可能是渲染——也许是在服务器端渲染一些预览图像,但它也可能只是进行 3D 计算,因为 three.js 拥有丰富的数学库。这是一个非常宽泛的术语。3D 的含义非常广泛。在大多数情况下,我们想到的是“图形”。.

我们看到的大多数 three.js 项目都涉及实时 3D 图形,用户交互会产生即时的视觉反馈。其他类型的 3D 图形要么是电影中的各种特效或人工角色,要么是你在印刷品或网络目录中可能看到的各种«渲染图»(例如,宜家的网站充满了 3D 图形,因为他们所有的产品照片都是计算机生成的)。.

所有这些内容的一个子集是 3D 数学。没有数学,就无法实现 3D 图形,而计算机语言默认情况下并不理解 3D 概念。这时就需要用到库,它抽象出这些数学运算,可能还会对其进行优化,并提供像 Matrix4 或 .dot() 这样的高级接口。.

Three.js 自带数学库,其中包含专门用于 3D 数学的类。虽然也有专门处理这类数学运算的独立库,但在 Three.js 中,它只是一个更大系统的一个子集。.

渲染是该库的另一项重要职责,但这里的情况也比较复杂。WebGL 非常特殊,与其他技术截然不同。.

使用 canvas、svg 和 css 时,渲染的责任完全在于 3D。这些 API 有许多用于绘制非 3D 图形的库,或者默认情况下就能够绘制非 3D 图形(css 绘制 2D 矩形,canvas 绘制各种 2D 形状),但它们需要一些技巧和 3D 数学运算才能真正实现 3D 渲染。.

这种神奇之处主要体现在界面抽象上。例如,管理元素的3D状态。 <div> 通过 CSS 转换为 3D 非常困难。要让 Canvas API 绘制出类似 3D 的效果,需要大量的逻辑。WebGL 则要复杂得多。.

Three 将所有这些 API 抽象成像 render() 这样简单的东西,但要做到这一点,它需要对“3D 世界”进行通用表示。.

场景图

在 three.js 中,有一个区域专门用于抽象«3D 世界»。场景图是一种数据结构,用于描述某个 3D 场景(世界)中的对象之间的关系。它实际上不一定是 3D 的,因为这是一种描述任何矢量图形层次结构的便捷方式。更具体地说,它是一个从“节点”向外延伸的“树”,其“根节点”是分支节点。在 three.js 中,这种数据结构的基类是 Object3D。.

这几乎与 DOM 树完全相同。THREE.Scene 也类似。 <body> 将会是,而其他一切都是分支。在 DOM 中,我们可以放置物体,但这些操作相对有限。旋转通常围绕一个轴进行,我们只能左右或上下移动物体。在 3D 场景图中,我们拥有更多的自由度。.

场景三更像是一个虚拟 DOM。我们在这个树上执行操作并设置状态,当我们需要该状态的视觉快照时(例如在连续循环中,或用户交互/状态更改时),我们会调用 render(scene)。当某些内容发生变化时,我们不希望更新整个 DOM 树,而对于元素来说,则无需更新整个 DOM 树。即使只有一个元素改变了位置,我们也必须清除整个视图,然后重新绘制所有内容。.

一 <div> 一 <div> 类似于父子关系 `THREE.Mesh(&#039;sun&#039;)-&gt;THREE.Mesh(&#039;earth&#039;)`。CSS 规则可以类似于 `THREE.Material`,例如,`color:&#039;red&#039;` 这样的描述会使物体变为红色。最后,调用 `threeRenderer.render(scene)` 可以类似于浏览器加载带有 CSS 规则的 HTML 页面。.

Mesh、Scene、Camera 和 Light 都是这个通用类的子类。正是由于这个通用类的存在,你才能向“scene”中添加一个“盒子”,或者向“camera”中添加一个“光源”。.

一个简单的结构可以非常扁平。根节点可以看作是“世界”,它可以有“地面”、“房子”、“太阳”和“相机”等子节点。.

THREE.Scene('world')
|-THREE.Mesh('ground')
|-THREE.Mesh('house')
|-THREE.Light('sun')
|-THREE.Camera('main')

这些信息足以输入渲染器以获得视觉效果。对于某些场景,存在两个网格分别代表不同的对象:地面和山坡上的房屋。光源定义了它们的照明方式(早晨、中午或闪光灯),而物体(摄像机)则定义了我们的视角,即我们对世界的感知。.

结果可能会有所不同,例如 CSS 仅限于非常轻量的渲染,而 WebGL 可以提供阴影和通常较高的保真度。.

通过这种结构,我们可以管理 3D 世界。如果我们想模拟不同季节日光对房屋的影响,就可以通过编程方式改变世界中光源的位置和方向。场景图的作用是提供这个“位置”接口,但要真正实现动画效果,则需要自行实现逻辑。使用 three.js 及其“补间动画”库是实现 3D 场景动画的简单方法。.

这一切可能都只是理论上的,你或许无法随意更改场景渲染。但这主要是由于“材质”与场景图的重叠以及它们与渲染的耦合造成的。例如,你无法对一个场景进行着色。 <div> 或者它看起来不像金属,而 WebGL 材质可以描述金属,但它可以变成红色,而所有材质都可以做到这一点。.

从本质上讲,Object3D 仍然是通用的,节点之间的空间和层次关系是通过“场景图”来描述的。.

简单来说,这是多次调用 scene.add(my_foo) 后最终得到的场景变量。.

WebGL

WebGL 非常特殊,可能在 99% 的现有 three.js 应用中都使用。这是一个很大的话题,所以或许应该先快速了解一下其他替代方案。.

canvas、css、svg

这些都是API(应用程序接口)。程序员可以使用API接口来告诉浏览器绘制特定的内容。CSS是Web上最常用的接口,因为如果没有它,所有内容看起来都像纯文本。从历史上看,它与3D并无关联。.

Canvas 实际上使用相同的 WebGL 元素进行绘制,但上下文不同。该上下文实际上被称为“2D”,但由于 3D 本身是伪的,我们始终绘制的是某种 2D 表面(无论是真实的还是虚拟的),因此我们也可以使用此上下文来绘制 3D 图形。.

SVG 是另一种非 3D API,通常用于描述徽标或图标等内容。但是,由于它可以描述线条等基本事物,因此也可以在 3D 环境中表示(例如地图上的叠加层,或具有空间感知能力的 UI 或 HUD 元素)。.

这些工具的共同点在于它们都不适用于 3D 应用。另一个重要特点是它们都是高级工具——它们最初的设计用途并非如此。例如,这三种工具都能够绘制“圆”。使用 Canvas,这是一个明确的形状;使用 CSS,你可能需要设置圆角半径,但最终都能直接绘制出一个圆。.

WebGL 的底层实现非常有限,它对 3D 图形的概念了解甚少。3D 图形需要进行特定的数学计算,而且计算量非常大。试想一下高分辨率屏幕及其像素数量。如果需要对每个像素进行计算,以确定一定量的光线如何影响屏幕表面,并且每秒要进行 60 次这样的计算,那么计算量就会非常惊人。.

图形处理器

大多数计算机,例如笔记本电脑、台式电脑、手机,甚至智能手表,都配备某种硬件设备,可以高效地计算这些3D运算,并显示交互式图形。这种设备被称为图形处理单元(GPU)。.

它与主处理器不同,因为它是为不同的目的而构建的——执行特定的并行数学运算。.

就像我们使用 JavaScript 进行浏览器编程一样,我们使用 WebGL 进行显卡编程。.

理论上没错,但实际上它们是两种截然不同的东西。WebGL 由 JavaScript 代码(指令)和一种完全不同的语言(GLSL)组成,后者负责实际的计算。你可以将 HTML 和 JavaScript 进行一些类比,看看它们如何在页面上协同工作。.

二维和三维

硬件加速不仅能提升 3D 图形处理能力,视频处理也是不错的选择。你可以对显卡进行编程,使其改变实时视频流中的颜色或图像。.

WebGL 是一种底层技术,具有通用性。它不了解 2D 或 3D,但它了解内存、缓冲区、命令队列、着色器等等。.

并行编程与 JavaScript 编程截然不同。一个常见的问题是不同线程如何访问共享变量。.

这种不同的范式意味着需要一种名为 GLSL 的全新语言。它是一种着色语言,几乎存在于所有底层图形 API 中。你可以在这里编写处理这些大数值的实际逻辑,唯一的优势就是无需编写机器代码。.

WebGL API 的另一部分是 JavaScript 绑定,通过这些绑定,你可以告诉 GPU 执行某些操作。例如,着色器可以“执行计算 A”,绑定可以“运行一百万次”。.

程序员需要自行计算 A 是什么。它可能与 3D 相关,也可能是一个用于模糊视频的内核。.

当你开始抽象这些计算和命令时,最终你会得到 three.js。.

相互配合的渲染图

一个很有意义的应用场景是结合使用多种渲染器来绘制“3D”效果出色的图形。WebGL 可以处理大量数据并创建非常逼真的图像,但它在处理文本甚至某些线条方面却很弱。额外的渲染文本层可以通过 CSS 和 canvas 渲染器来处理,而路径和各种线条则可以通过 SVG 来处理。.

THREE.WebGL渲染器

所有这些底层操作都通过 three.js 的 WebGLRenderer 类进行了抽象。正是这个类将立方体转换成了 GPU 内存中的一堆数字。.

讽刺的是,WebGL 是 three.js 中唯一不需要处理 3D 图形的渲染器,但却是处理 3D 图形的最佳选择。其他渲染器使用 2D API 来模拟 3D 效果,而 WebGL 则使用通用的并行计算 API 来实现真正的 3D 效果。但这并不排除将其专门用于处理实时视频流的可能性。它对 WebGL 进行了足够的抽象,使其能够胜任这项工作,但你可能只用到了库的三分之一。你可以使用 WebGL 构建一个响应速度极快的 UI 层,或者开发一款类似超级马里奥的平台游戏,在这些游戏中,three.js 仍然是一个强大的工具。.

你只使用了库的三分之一,这意味着可能还有其他工具更适合你的用途,或者你可以只构建 three.js 的一个子集。超级马里奥和视频处理示例可能都只需要 PlaneGeometry 和材质类型。.

三数学

这段 JavaScript 代码可以在 3D 空间中执行特定的数学运算。JS 默认提供了 `Math.pow()` 方法,但没有 `Quaternion.inverse()` 方法。利用这些类,我们可以编写不需要渲染的算法——例如,一个游戏服务器可以验证谁在射击,发送大量光线但无需绘制任何内容。.

三幅场景图

这是一系列 Object3D 子类,它们构成了一个树状数据结构,用于描述“3D 世界”及其内部对象之间的关系。虽然概念上比较抽象,但一旦深入代码,就可以通过特定的渲染方式进行一定程度的渲染。.

三张渲染图

该层将通用图转换为屏幕或缓冲区(例如,在服务器端创建)上的可视化表示。它使用多种技术来实现这一目标。.

THREE-WebGL渲染器

它是一种特殊的渲染器,支持硬件加速,并且精通许多 3D 概念,但也可以用于 2D(甚至通用计算)。在我看来,这些是 three.js 的主要构建模块。我倾向于用“图形”代替“3D”,但这仅适用于 WebGLRenderer。.

Three.js 不是游戏引擎。

并非所有需要在网页上使用 3D(或图形)的人都在制作游戏。游戏引擎通常会在描述和显示 3D 世界之外进行大量优化。不同的游戏有不同的需求,即时战略游戏和第一人称射击游戏的物理引擎和渲染系统很可能有着截然不同的需求。所有这些都意味着需要编写更多代码,而对于只想快速搭建一个 3D 模型作为产品目录一部分的人来说,这不仅没有必要,而且也不可取。当然,你也可以构建一个游戏引擎,然后使用三个引擎分别用于渲染和构建引擎模块。.

Three.js 加载速度很慢。

当然,核心库针对某些资源提供了多个加载器,但所有常见的格式(例如 glTF 或 FBX)都是独立的。Three.js 并不关心你如何获取资源,只要你能正确解析它们并创建 3D 对象即可。在 Three.js 看来,glTF 文件中的网格和程序生成的球体之间没有任何区别。许多创意示例都使用立方体和球体,并且除了 Three.js 本身之外,不加载任何其他内容。核心加载器非常通用,可以加载图像和文件,并直接表示 Three.js 对象,例如材质或纹理。特定格式的加载器就是基于这些基本组件构建的。.

 

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

您可能也喜欢