第七章点和精灵

在前几章中,我们讨论了Three.js具有的最重要的概念、对象和API提供。在本章中,我们将探讨到目前为止我们跳过的唯一概念:点和精灵。使用THREE.Points(有时也称为精灵),可以很容易地创建许多小矩形始终面向相机,您可以使用它来模拟雨、雪、烟和其他有趣的效果。例如,可以将单个几何体渲染为一组点,并分别控制这些点。在本章中,我们将探讨Three.js提供的各种与点和精灵相关的功能。

更具体地说,我们将介绍本章中的以下主题:

  • 使用 THREE.SpriteMaterial 和 THREE.PointsMaterial 创建粒子并设置粒子样式
  • 使用 THREE.Points 创建一组点
  • 使用画布单独设置每个点的样式
  • 使用纹理为各个点设置样式
  • 设置THREE.Points对象的动画
  • 根据现有几何图形创建 THREE.Points 对象

快速说明本章中使用的一些名称

在Three.js的新版本中,与点相关的对象的名称已经更改了好几次。THREE.Points对象以前被命名为THREE.PointCloud,在更旧的版本中,它被称为THREE.ParticleSystem.THREE.Sprite过去被称为THREE.Particle,这些材质也经历了几次名称更改。所以,如果你在网上看到使用这些旧名字的例子,请记住他们谈论的是相同的概念。

让我们先探索粒子是什么以及如何创建粒子。

理解点和精灵

正如我们处理大多数新概念一样,我们将从一个示例开始。在本章的源代码中,您将找到一个名为sprite.html的例子。打开这个示例后,您将看到一个极简主义的场景,其中包含一个简单的彩色正方形:

image-20230522143129933

图7.1-一个单独渲染的精灵

您可以使用鼠标围绕此场景旋转。你会注意到的一件事是,无论你怎么看这个广场,它看起来总是一样的。例如,下面的屏幕截图显示了来自不同位置的同一场景的视图:

image-20230522143301778

图7.2-一个单独渲染的精灵将始终面对着摄像机

正如你所看到的,精灵仍然朝着相机倾斜,你不能看它的后面。你可以把精灵想象成一个始终面向相机的2D平面。如果创建一个没有任何属性的精灵,它们将渲染为白色的二维小正方形。要创建精灵,我们只需要提供一种材质:

const material = new THREE.SpriteMaterial({ size: 0.1, color: 0xff0000 })
const sprite = new THREE.Sprite(material)
sprite.position.copy(new THREE.Vector3(1,1,1))

您可以使用THREE.SpriteMaterial配置精灵的显示方式:

  • color:这是精灵的颜色。默认颜色为白色。
  • sizeAttenuation:如果设置为false,则无论精灵位于离摄影机多远的位置,精灵都将具有相同的大小。如果设置为true,则大小基于与摄影机的距离。默认值为true。请注意,这只有在使用THREE.PerspectiveCamera时才有效果。对于THREE.OthographicCamera,如果设置为false,它总是起作用。
  • map:使用此属性,您可以将纹理应用到精灵中。例如,你可以让它们看起来像雪花。这个属性在本示例中没有显示,但在本章的纹理部分中解释。
  • opacity:这与透明属性一起,设置了精灵的不透明度。默认值为1(完全不透明)。
  • transparent:如果此设置为true,则将使用不透明度属性设置的不透明度渲染精灵。默认值为假值。
  • blending:这是在渲染精灵时要使用的混合模式。

请注意,THREE.SpriteMaterial是从基本的THREE.Material对象扩展而来的,因此该对象的所有属性也可以在THRE.SpriteMaterial上使用。

在我们继续讨论更有趣的THREE.Points对象之前,让我们仔细看看THREE.Sprite对象。THREE.Sprite对象从THREE.Object3D对象延伸,就像THREE.Mesh一样。这意味着你从THREE.Sprite中知道的大多数属性和函数。Mesh可以在THREE.Sprite上使用。你可以使用位置属性、比例来设置它的位置它使用scale属性,并使用translate属性沿其轴移动。

使用THREE.Sprite,您可以非常容易地创建一组对象并在场景中移动它们。当你处理少量对象时,这很好,但当你想处理大量的THREE.Sprite对象时,你会很快遇到性能问题。这是因为每个对象都需要由Three.js单独管理。Three.jss提供了一种使用Three.Points对象处理大量精灵的替代方法。使用THREE.Points,THREE.js不必管理许多单独的THREE.Sprite对象,只需管理THREE.Pointss实例即可。这将允许Three.js优化绘制精灵的方式,并将获得更好的性能。以下屏幕截图显示了使用THREE.Points对象渲染的几个精灵:

image-20230522144047183

图7.3-从THREE.BufferGeometry渲染的多个点

要创建一个THREE.Points对象,我们需要为其提供THRE.BufferGeometry。对于之前的屏幕截图,我们可以创建一个THRE.BBufferGeometry,如下所示:

const createPoints = () => {
 const points = []
 for (let x = -15; x < 15; x++) {
 for (let y = -10; y < 10; y++) {
 let point = new THREE.Vector3(x / 4, y / 4, 0)
 points.push(point)
 }
 }
 const colors = new Float32Array(points.length * 3)
 points.forEach((e, i) => {
 const c = new THREE.Color(Math.random() * 0xffffff)
 colors[i * 3] = c.r
 colors[i * 3 + 1] = c.g
 colors[i * 3 + 2] = c.b
 })
 const geom = new THREE.BufferGeometry().setFromPoints(points)
 geom.setAttribute('color', new THREE.BufferAttribute(colors, 
3, true))
 return geom
}
const material = new THREE.PointsMaterial({ size: 0.1,vertexColors: true, color: 0xffffff })
const points = new THREE.Points(createPoint(), material)

正如您从这个代码片段中看到的那样,首先,我们创建一个THREE.Vector3对象的数组——每个位置都有一个我们想要创建精灵的对象。此外,我们在THREE.BufferGeometry上设置了颜色属性,该属性用于为每个精灵着色。使用THREE.BufferGeometry和 THREE.PointsMaterial的实例,我们可以创建THREE.Points对象。THRE.PointsMaterial的属性与THRE.SpriteMaterial的属性基本相同:

  • color:这是这个点的颜色。默认颜色为0xffffff
  • sizeAttenuation:如果设置为false,所有点的大小都是相同的,无论它们的位置离相机有多远。如果此设置为true,则大小将基于与相机的距离。默认值为真。
  • map:使用此属性,您可以将纹理应用到该点。例如,你可以让它们看起来像雪花。这个属性在本示例中没有显示,但在本章后面的样式粒子使用纹理部分中解释。
  • opacity:这与 transparent 属性一起设置精灵的不透明度。默认值为1(不透明度)。
  • transparent:如果此设置为true,则精灵将使用不透明度属性设置的不透明度进行渲染。默认值为 false
  • blending:这是在渲染精灵时要使用的混合模式。
  • vertexColors:通常情况下 THREE.Points 的所有点都有相同的颜色。如果这样属性设置为true,并且已经在几何体上设置了颜色的缓冲区属性,则每个点都将从该数组中获取颜色。默认值为false

与往常一样,您可以使用每个示例中右边的菜单来处理这些属性。

到目前为止,我们只将粒子渲染为小的正方形,这是默认的行为。但是,还有两种方法可以样式粒子,我们将在下一节中展示。

使用纹理样式化粒子

在本节中,我们将介绍以下两种改变精灵外观的方法:

  • 使用HTML画布绘制一个图像,并显示为每个精灵
  • 加载一个外部图像文件,以定义每个精灵的外观

让我们从自己绘制图像开始。

在画布上绘制图像

在THRE.PointsMaterial的属性中,我们提到了map属性。使用map属性,我们可以为各个点加载纹理。使用Three.js,这个纹理也可以是HTML5画布的输出。在我们看代码之前,让我们看一个例子(canvastexture.js):

image-20230523133729523

图7.4-使用基于画布的纹理创建精灵

在这里,你可以看到我们在屏幕上有一大群吃豆人一样的鬼魂。这使用了与我们之前在理解点和精灵部分中看到的相同的方法。不过,这次我们展示的不是一个简单的正方形,而是一个图像。要创建此纹理,我们可以使用以下代码:

const createGhostTexture = () => {
 const canvas = document.createElement('canvas')
 canvas.width = 32
 canvas.height = 32
 const ctx = canvas.getContext('2d')
 // the body
 ctx.translate(-81, -84)
 ctx.fillStyle = 'orange'
 ctx.beginPath()
 ctx.moveTo(83, 116)
 ctx.lineTo(83, 102)
 ctx.bezierCurveTo(83, 94, 89, 88, 97, 88)
 // some code removed for clarity
 ctx.fill()
 // the eyes
 ctx.fillStyle = 'white'
 ctx.beginPath()
 ctx.moveTo(91, 96)
 ctx.bezierCurveTo(88, 96, 87, 99, 87, 101)
 ctx.bezierCurveTo(87, 103, 88, 106, 91, 106)
 // some code removed for clarity
 ctx.fill()
 // the pupils
 ctx.fillStyle = 'blue'
 ctx.beginPath()
 ctx.arc(101, 102, 2, 0, Math.PI * 2, true)
 ctx.fill()
 ctx.beginPath()
 ctx.arc(89, 102, 2, 0, Math.PI * 2, true)
 ctx.fill()
 const texture = new THREE.Texture(canvas)
 texture.needsUpdate = true
 return texture
}

正如你所看到的,首先,我们创建了一个HTML画布,在上面我们开始使用各种ctx.函数进行绘制。最后,我们通过调用新的THREE.Texture(画布)将这个画布转换为THREE.Texture,这将产生一个可以用于精灵的纹理。请记住将texture.needsUpdate设置为true,这将触发Three.js将实际画布数据加载到纹理中。

现在我们有了一个纹理,我们可以使用它来创建THREE.PointsMaterial,就像我们在理解点和精灵部分所做的那样:

const createPoints = () => {
 const points = []
 const range = 15
 for (let i = 0; i < 15000; i++) {
 let particle = new THREE.Vector3(
 Math.random() * range - range / 2,
 Math.random() * range - range / 2,
 Math.random() * range - range / 2
 )
 points.push(particle)
 }
 const colors = new Float32Array(points.length * 3)
 points.forEach((e, i) => {
 const c = new THREE.Color(Math.random() * 0xffffff)
 colors[i * 3] = c.r
 colors[i * 3 + 1] = c.g
 colors[i * 3 + 2] = c.b
 })
 const geom = new THREE.BufferGeometry().setFromPoints(points)
 geom.setAttribute('color', new THREE.BufferAttribute(colors, 3, true))
 return geom
}
const material = new THREE.PointsMaterial({ size: 0.1, vertexColors: true, color: 0xffffff, map:
 createGhostTexture() })
 const points = new THREE.Points(createPoint(), material)

正如您所看到的,我们为这个例子创建了15000个点,并将它们随机放置在指定的范围内。你可能会注意到,即使你打开了透明度,一些精灵似乎会与其他精灵重叠。这是因为Three.js不会根据精灵的z索引对其进行排序,所以在渲染时,它无法正确地确定哪个在另一个之前。有两种方法可以解决这个问题:可以关闭depthWrite,也可以使用alphaTest属性(从0.5开始是一个很好的起点)。

如果你缩小范围,你将看到15000个个体精灵:

image-20230523134435103

图7.5-同时显示了15000个精灵

令人惊讶的是,即使有100万个点,一切都能非常平滑地渲染(当然,这取决于运行这些示例的硬件):

image-20230523134621673

图7.6-同时显示了100万个精灵

在下一节中,我们将从外部图像中加载一些纹理,并使用这些纹理,而不是自己绘制纹理。

使用纹理来设定粒子的样式

使用HTML画布进行点操作。由于可以绘制任何需要的东西,甚至可以加载外部图像,因此可以使用此方法将各种样式添加到粒子系统中。然而,有一种更直接的方法可以使用图像来设置粒子的样式:您可以使用THREE.TextureLoader().load() 函数将图像加载为THREE.Texture对象。然后可以将此THREE.Texture对象指定给材质的贴图属性。在本节中,我们将向您展示两个示例,并解释如何创建它们。这两个例子

使用图像作为粒子的纹理。在第一个示例中,我们将创建一个降雨模拟(rain.html):

image-20230523135024914

图7.7:模拟降雨下降

我们需要做的第一件事是获得一个能代表雨滴的纹理。您可以在 assets/textures/particles 文件夹中找到几个示例。在接下来的章节中,我们将解释纹理的所有细节和要求。目前,您只需要知道纹理应该是正方形的,最好是2的幂(例如,64 x 64、128 x 128或256 x 256)。对于本例,我们将使用以下纹理:

image-20230523135221452

图7.8:雨滴纹理

这个纹理是一个简单的透明图像,显示雨滴的形状和颜色。在THREE.PointsMaterial中使用此纹理之前,我们需要加载它。这可以通过以下代码行完成:

const texture = new THREE.TextureLoader().load("../../assets/textures/particles/raindrop-3t.png");

有了这行代码,Three.js将加载纹理,我们可以在材料中使用它。对于本例,我们将材料定义如下:

const material = new THREE.PointsMaterial({
 size: 0.1,
 vertexColors: false,
 color: 0xffffff,
 map: texture,
 transparent: true,
 opacity: 0.8,
 alphaTest: 0.01
 }),

在本章中,我们已经讨论了所有这些属性。这里要理解的主要内容是,map属性指向我们使用THREE.TextureLoader.load函数加载的纹理。请注意,我们再次使用了alphaTest属性,以确保当两个精灵在彼此前面移动时不会出现奇怪的伪影。

这就处理了THREE.Points对象的样式。当你打开这个例子时,你还会看到点本身在移动。这样做非常简单。每个点都表示为一个顶点,该顶点构成用于创建THREE.Points对象的几何体。让我们看看如何为这个点添加 THREE.Points 对象:

const count = 25000
const range = 20
const createPoints = () => {
 const points = []
 for (let i = 0; i < count; i++) {
 let particle = new THREE.Vector3(
 Math.random() * range - range / 2,
 Math.random() * range - range / 2,
 Math.random() * range - range / 1.5
 )
 points.push(particle)
 }
 const velocityArray = new Float32Array(count * 2)
 for (let i = 0; i < count * 2; i += 2) {
 velocityArray[i] = ((Math.random() - 0.5) / 5) * 0.1
 velocityArray[i + 1] = (Math.random() / 5) * 0.1 + 0.01
 }
 const geom = new THREE.BufferGeometry().setFromPoints(points)
 geom.setAttribute('velocity', new THREE.
BufferAttribute(velocityArray, 2))
 return geom
}
const points = new THREE.Points(geom, material);

这与我们在本章中看到的前面的例子没有什么不同。在这里,我们为每个粒子添加了另一个特性,称为速度。此属性由两个值组成:velocityX和velocityY。第一个定义了粒子(雨滴)如何水平移动,而第二个定义了雨滴下落的速度。现在,每个雨滴都有自己的速度,我们可以在渲染循环中移动单个粒子

const positionArray = points.geometry.attributes.position.array
const velocityArray = points.geometry.attributes.velocity.array
for (let i = 0; i < points.geometry.attributes.position.count; i++) {
 const velocityX = velocityArray[i * 2]
 const velocityY = velocityArray[i * 2 + 1]
 positionArray[i * 3] += velocityX
 positionArray[i * 3 + 1] -= velocityY
 if (positionArray[i * 3] <= -(range / 2) || positionArray[i * 3] >= range / 2)
 positionArray[i * 3] = positionArray[i * 3] * -1
 if (positionArray[i * 3 + 1] <= -(range / 2) || positionArray[i * 3 + 1] >= range / 2) 
     positionArray[i * 3 + 1] = positionArray[i * 3 + 1] * -1
}
points.geometry.attributes.position.needsUpdate = true

在这段代码中,我们从用于创建THREE.Points的几何体中获取所有顶点(粒子)。对于每个粒子,我们获取velocityX和velocityY,并使用它们来更改粒子的当前位置。然后,我们确保粒子保持在我们定义的范围内。如果v.y位置下降到0以下,我们将雨滴添加回顶部,如果v.x位置到达任何边缘,我们通过反转水平速度使其反弹。最后,我们需要告诉Three.js我们已经更改了bufferGeometry中的一些内容,以便它在下次渲染时知道正确的值

让我们来看看另一个例子。这一次,我们不会下雨;相反,我们会造雪。此外,我们不会只使用一个纹理——我们将使用三个独立的图像(来自Three.js示例)。让我们先看一下结果(snow.html)开始:

image-20230524134534469

图7.9-基于多个纹理的雪地场景

在前面的屏幕截图中,如果你仔细观察,你可以看到,我们使用了多个具有透明背景的图像,而不是只使用一个图像作为纹理。你可能想知道我们是怎么做到的。你可能还记得,我们只能用一种材料来制作 THREE.Points 对象如果我们想要有多个材料,我们只需要制作多个 THREE.Points 实例,如下所示:

const texture1 = new THREE.TextureLoader().load('/assets/textures/particles/snowflake4_t.png')
const texture2 = new THREE.TextureLoader().load('/assets/textures/particles/snowflake2_t.png')
const texture3 = new THREE.TextureLoader().load('/assets/textures/particles/snowflake3_t.png')
const baseProps = {
 size: 0.1,
 color: 0xffffff,
 transparent: true,
 opacity: 0.5,
 blending: THREE.AdditiveBlending,
 depthTest: false,
 alphaTest: 0.01
}
const material1 = new THREE.PointsMaterial({
 ...baseProps,
 map: texture1
})
const material2 = new THREE.PointsMaterial({
 ...baseProps,
 map: texture2
})
const material3 = new THREE.PointsMaterial({
 ...baseProps,
 map: texture3
})
const points1 = new THREE.Points(createPoints(), material1)
const points2 = new THREE.Points(createPoints(), material2)
const points3 = new THREE.Points(createPoints(), material3)

在这个代码片段中,您可以看到我们创建了三个不同的three.Points实例,每个实例都有自己的材质。为了移动雪花,我们使用了与降雨相同的方法,所以我们在这里不显示createPoint和渲染循环的细节。这里需要注意的一点是,可以有一个单独的THREE.Points实例,其中单个精灵具有不同的纹理。但是,这需要一个自定义 fragment-shader (片段着色器)和您自己的THRE.ShaderMaterial实例。

在我们进入下一节之前,请注意使用THREE.Points是为现有场景添加视觉效果的好方法。例如,我们在上一个示例中看到的雪可以快速将标准场景转换为雪地场景:

image-20230524135006411

图7.10-3。点和立方体贴图

我们使用精灵的另一种方法是在现有场景的顶部创建一个简单的2D平视显示器(HUD)。我们将在下一节中探讨如何做到这一点。

使用精灵贴图

在本章的开头,我们使用了一个THREE.Sprite对象来渲染单个点。这些精灵位于3D世界的某个地方,它们的大小取决于与相机的距离(有时也称为Billboard)。在本节中,我们将展示THREE.Sprite对象的另一种用法:我们将向您展示如何使用THREE.Sprite,使用额外的THREE.OrthographicCamera实例和额外的THREE.Scene为3D内容创建类似于HUD的层。我们还将向您演示如何使用Sprite贴图为THREE.Sprit对象选择图像

例如,我们将创建一个简单的THREE.Sprite对象,该对象在屏幕上从左向右移动。在背景中,我们将使用相机渲染3D场景,您可以移动相机来说明THREE.Sprite对象独立于相机移动。下面的屏幕截图显示了我们将为第一个示例(spritemap.html)创建的内容:

image-20230524135528707

图7.11-使用两个场景和摄像机来创建一个HUD

如果你在浏览器中打开这个例子,你会看到一个吃豆人幽灵般的精灵在屏幕上移动,每当它碰到右边缘时,就会改变颜色和形状。我们要做的第一件事是看看如何创建THREE.OrthographicCamera和一个单独的场景来渲染 THREE.Sprite

const sceneOrtho = new THREE.Scene()
sceneOrtho.backgroundColor = new THREE.Color(0x000000)
const cameraOrtho = new THREE.OrthographicCamera(0, window.
innerWidth, window.innerHeight, 0, -10, 10)

接下来,让我们看看这三个结构的构造。精灵对象和如何,精灵可以采取的各种形状被加载

const getTexture = () => {
 const texture = new THREE.TextureLoader().load
 ('/assets/textures/particles/sprite-sheet.png')
 return texture
}
const createSprite = (size, transparent, opacity, spriteNumber) 
=> {
 const spriteMaterial = new THREE.SpriteMaterial({
 opacity: opacity,
 color: 0xffffff,
 transparent: transparent,
 map: getTexture()
 })
 // 我们有一排,有五个精灵
 spriteMaterial.map.offset = new THREE.Vector2(0.2 * spriteNumber, 0)
 spriteMaterial.map.repeat = new THREE.Vector2(1 / 5, 1)
 // 确保该对象总是在前面被渲染
 spriteMaterial.depthTest = false
 const sprite = new THREE.Sprite(spriteMaterial)
 sprite.scale.set(size, size, size)
 sprite.position.set(100, 50, -10)
 sprite.velocityX = 5
 sprite.name = 'Sprite'
 sceneOrtho.add(sprite)
}

在 getTexture() 函数中,我们加载一个纹理。然而,我们不是为每个重影加载五个不同的图像,而是加载一个包含所有精灵的纹理(也称为精灵贴图)。作为纹理的图像如下所示:

image-20230524135923341

图7.12-输入精灵的工作表

使用 map.offset 和 map.repeat 属性,我们可以选择要在屏幕上显示的正确精灵。使用 map.offset 属性,我们确定加载纹理的x轴(u)和y轴(v)的偏移。这些属性的比例从0到1。在我们的示例中,如果我们想选择第三个重影,我们必须将u偏移(x轴)设置为0.4,并且,因为我们只有一行,所以不需要更改v偏移(y轴)。如果我们只设置此属性,纹理会在屏幕上显示压缩在一起的第三个、第四个和第五个重影。要只显示一个重影,我们需要放大。我们可以通过将u值的 map.repeak 属性设置为1/5来实现这一点。这意味着我们放大(仅针对x轴)以仅显示20%的纹理,这正好是一个重影。

最后,我们需要更新渲染功能:

 renderer.render(scene, camera)
 renderer.autoClear = false
 renderer.render(sceneOrtho, cameraOrtho)

首先,我们用普通照相机和两个网格渲染场景;之后,我们渲染包含我们的精灵的场景。在渲染循环中,我们还会切换一些属性来显示下一个精灵击中右边的墙,并改变精灵的方向(代码未显示)。

在本章中,到目前为止,我们主要研究了从零开始创建精灵和点云。不过,一个有趣的选择是创建 THREE.Points 从现有几何图形中获得的点

从现有集合创建 THREE.Points

您可能还记得,THREE.Points根据提供的THRE.BufferGeometry中的顶点渲染每个点。这意味着,如果我们提供复杂的几何体(例如,圆环结或管),我们可以根据特定几何体中的顶点创建THREE.Points。在本章的最后一节中,我们将创建一个圆环结,就像我们在第6章“探索高级几何”中看到的那样,并将其渲染为THREE.Points对象。

在本章的最后一节,我们将创建一个圆环结,就像我们在第6章“探索高级几何”中看到的那样,并将其渲染为THREE.Points对象。

我们在第六章中解释了环面结,所以我们不会在这里进行详细介绍。下面的屏幕截图显示了该示例(points-from-geom.html):

image-20230524140812897

图7.13-环面结渲染为点的小动画

从前面的屏幕截图中可以看到,用于生成圆环结的每个顶点都用作一个点。我们可以这样设置:

const texture = new THREE.TextureLoader().load('/assets/textures/particles/glow.png')
const geometry = new THREE.TorusKnotGeometry(2, 0.5, 100, 30, 
2, 3)
const material = new THREE.PointsMaterial({
 size: 0.2,
 vertexColors: false,
 color: 0xffffff,
 map: texture,
 depthWrite: false,
 opacity: 0.1,
 transparent: true,
 blending: THREE.AdditiveBlending
 })
const points = new THREE.Points(geometry, material)

正如您所看到的,我们只需创建一个几何体,并将其用作THREE.Points对象的输入。通过这种方式,我们可以将每个几何体渲染为点对象。

注意

如果您使用Three.js模型加载器(例如,glTF模型)加载外部模型,您通常会得到一个对象层次结构——通常分组为Three.Group或THRE.Object3D对象。在这种情况下,您必须将每组中的每个几何体转换为一个THREE.Points对象。

总结

这是本章的总结。我们已经解释了什么是精灵和点,以及如何使用可用的材质设置这些对象的样式。在本章中,您了解了如何直接使用THREE.Sprite,并且如果您想创建大量粒子,则应该使用THREE.Points对象。使用THREE.Points,所有元素共享相同的材质,通过将材质的verteColors属性设置为true并在用于创建THRE.Points的THRE.BufferGeometry的颜色数组中提供颜色值,可以更改单个粒子的唯一属性是其颜色。我们还展示了如何通过更改粒子的位置轻松设置粒子动画。这对单个THREE.Sprite实例和用于创建THREE.Points对象的几何体中的顶点也是一样的。

到目前为止,我们已经根据Three.js提供的几何图形创建了网格。这对简单的模型(如球体和立方体)很有效,但当你想创建复杂的3D模型时,这不是最好的方法。对于这些模型,您通常会使用3D建模应用程序,如Blender或3D Studio Max。在下一章中,您将了解如何加载和显示由此类3D建模应用软件创建的模型。