和我一起学 Three.js 【初级篇】:2. 掌握几何体

本篇文章共 5090 字,最近更新于 2023 年 04 月 19 日。

0. 系列文章合集

本系列第 6,7,8 章节支持在我的个人公众号「前端乱步」内付费观看,将在全平台文章「点赞数」+「评论数」 >= 500(第 6 章), 1000(第 7,8 章) 时分别解锁发布。

  1. 《和我一起学 Three.js【初级篇】:0. 总论》
  2. 《和我一起学 Three.js【初级篇】:1. 搭建 3D 场景》
  3. 您当前在这里《和我一起学 Three.js【初级篇】:2. 掌握几何体》
  4. 《和我一起学 Three.js【初级篇】:3. 掌握摄影机》
  5. 《和我一起学 Three.js【初级篇】:4. 掌握纹理》
  6. 《和我一起学 Three.js【初级篇】:5. 掌握材质》
  7. 《和我一起学 Three.js【初级篇】:6. 掌握光照》
  8. 《和我一起学 Three.js【初级篇】:7. 掌握阴影》
  9. 《和我一起学 Three.js【初级篇】:8. 融会贯通》

1. 什么是几何体(Geometry)

在 Three.js 的世界中,几何体(Geometry)由顶点(vertices),线,面组成,被用来定义物体的「形状」和「大小」

如果您想要在 3D 世界中「创造」某个物体,您需要首先确定这个物体「长什么样」?然后您就可以通过以下三种方式,创造出该物体:

  1. 使用 Three.js 提供的几何体对象
  2. 使用 Three.js 提供的 API 创建自定义几何体例如创建粒子动画);
  3. 通过 3D 软件导入模型

在本篇文章中,我们将只介绍前两种创建几何体的方式,在后续很多场景中,您会经常通过这两种方式实现您想要的效果。

2. 几何体与 3D 物体的关系

我们在上一篇文章提到过,在 Three.js 中创建一个「3D 物体」必须通过实例化一个「网格对象(Mesh)」实现。几何体(Geometry),材质(Material)和网格对象(Mesh)三者的关系像是一个金字塔。

和我一起学 Three.js 【初级篇】:2. 掌握几何体_第1张图片

「几何体」描述物体的形状和大小,「材质」描述物体的外观和质地,「网格对象」则将两者合并在一起,并提供使物体移动,旋转的能力。因此,要想当好 Web 3D 世界的造物主,您需要对这三个概念非常熟悉。

3. 学习几何体

您需要了解,Three.js 提供的所有现成的几何体,都继承自 BufferGeometry 对象,并且该对象也是 Three.js 为我们提供的创建自定义几何体的 API。因此,要学习几何体,我们要先从该对象说起。

3.1 BufferGeometry 对象

顾名思义,BufferGeometry 对象和「缓冲」相关,具体而言,该对象能够将几何体的相关数据(如顶点,UV,法线等)存入 GPU 的缓冲区(即显存),从而极大的提高 GPU 渲染性能与内存使用效率。

在计算机中,CPU 通常拥有更高的时钟速度和更大的缓存容量,但是并行计算的能力较差,难以处理大量的数据。而 GPU 的并行计算能力特别强,因此能够同时处理大量数据,但是缓存容量较小,时钟速度也较低。而针对 3D 渲染场景,大量的顶点数据需要在一次渲染中同时传递给 GPU 处理,因此对于这些数据的读写效率就成为了 GPU 渲染性能的瓶颈。因此,将顶点数据存储在缓冲区是现代 3D 渲染引擎中不可或缺的技术手段。

我们之前提到过,GPU 绘制几何体的过程,实际上是一个「读点」,「连线」和「结面」的过程。这里「读点」的「点」,指的就是几何体的「顶点」,它来源自开发者的输入,输入到哪里呢?在 Three.js 中,输入至 BufferGeometry 对象。

3.2 通过 BufferGeometry 对象绘制自定义几何体

为了绘制几何体,我们需要设定几何体的「顶点(vertices)」,每个顶点都至少由 3 个数字组成,表示其在空间直角坐标系内的位置。在一个颇具规模的 3D 世界中,我们有一定数量的几何体,意味着我们有大量的顶点数据需要 GPU 解析计算。因此,我们需要一种高效的数据结构存储顶点数据,在 JavaScript 世界中,我们通常使用 Float32Array 这一类型数组。

3.2.1 关于 Float32Array

Float32Array 是 JavaScript 提供的一种类型数组,用来存储 32 位浮点数(即表示 3.4028235 * 10 ^ 38 ~ 1.17549435 * 10 ^ -38 之间的任意数)。其函数签名为:

const array = new Float32Array(length | <Array>);

其中,length 参数表示数组的长度,它和普通数组的区别主要有如下两点:

  1. 数组中的每个元素的类型固定为采用 IEEE 754 标准表示的 32 位浮点数
  2. 它在实现方式上是一个「真正的数组」,即元素占据连续的内存空间

因此它是一种非常高效的数据结构,同时,由于其能够表示的数字范围较大,且可以表示的精度为小数点后 6 到 7 位,因此也非常适合用来存储顶点位置等数据。

3.2.2 自定义几何体

创建一个自定义几何体需要以下三个步骤:

  1. 使用数组定义几何体的顶点(使用 Float32Array 数据类型);
  2. 数组转换为一个** BufferAttribute **对象;
  3. 设置几何体的属性,并填充对应的值;

代码如下:

const geometry = new THREE.BufferGeometry()
const vertices = new Float32Array([
  -1.0, -1.0, 1.0,
   1.0,

你可能感兴趣的:(和我一起学,Three.js,javascript,前端,开发语言)