Three.js 使用入门

Paul Lewis

简介

我已使用 Three.js 进行一些实验,它很好地消除了在浏览器中使用 3D 的麻烦。借助该组件,您可以创建镜头、对象、灯光和材质等,并且可以选择渲染程序,这意味着您可以决定是否使用 HTML 5 的画布、WebGL 或 SVG 来绘制场景。由于它是开源的,您甚至可以参与项目。但现在,我将以所学的内容作为引擎,着重介绍我学到的知识,并介绍一些基础知识。

考虑到 Three.js 的出色之处,有时您可能会遇到困难。通常,您将需要花费大量时间来研究示例、逆向工程,以及(在我的情况下)发现特定功能,偶尔还会通过 GitHub 提问。顺便提一下,Mr. doobAlteredQualia 非常有帮助!

1. 基础知识

我会假设您至少通晓 3D 知识,并熟练掌握 JavaScript。如果不了解,不妨先稍微学习一下,然后再尝试使用这些东西,因为你可能会感到有点困惑。

在 3D 场景中,我们将呈现以下一些内容,我将引导您完成创建过程:

  1. 场景
  2. 渲染程序
  3. 相机
  4. 一两个物体(含材质)

当然,您可以做一些很酷的事情,我希望您继续做这些事情,并开始在浏览器中试用 3D。

2. 支持

这里简单说明一下浏览器支持情况。就支持哪些渲染程序以及底层 JavaScript 引擎的速度来看,Google 的 Chrome 浏览器是最适合兼容的浏览器。Chrome 支持画布、WebGL 和 SVG,速度极快。版本 4 问世后,Firefox 也跟上了其差距。虽然它的 JavaScript 引擎似乎比 Chrome 慢,但是它对呈现技术的支持同样非常出色。Opera 和 Safari 正在添加 WebGL 支持,但其当前版本仅支持画布。Internet Explorer(9 及更高版本)仅支持画布渲染,而且我还没有听说 Microsoft 计划添加任何 WebGL 功能的消息。

3. 设定场景

假设您选择的浏览器支持所有呈现技术,而且您希望使用画布或 WebGL 进行呈现,因为这两种技术是更标准的选择。与 WebGL 相比,画布的支持范围更广,但值得注意的是,WebGL 可以在显卡的 GPU 上运行,这意味着您的 CPU 可以专注于其他非渲染任务,例如您尝试执行的任何物理或用户互动任务。

请注意,无论您选择哪种渲染程序,JavaScript 都需要针对性能进行优化。3D 并不是浏览器的轻量级任务(甚至能够实现这一点的感觉很棒),因此请务必仔细了解代码中存在的任何瓶颈,并尽可能将其移除!

既然如此,再假设您已下载自己的 HTML 文件并在 HTML 文件中添加了 three.js,那么,您如何设置场景呢?示例如下:

// set the scene size
var WIDTH = 400,
HEIGHT = 300;

// set some camera attributes
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000;

// get the DOM element to attach to
// - assume we've got jQuery to hand
var $container = $('#container');

// create a WebGL renderer, camera
// and a scene
var renderer = new THREE.WebGLRenderer();
var camera = new THREE.PerspectiveCamera(
                VIEW_ANGLE,
                ASPECT,
                NEAR,
                FAR );

var scene = new THREE.Scene();

// the camera starts at 0,0,0 so pull it back
camera.position.z = 300;

// start the renderer
renderer.setSize(WIDTH, HEIGHT);

// attach the render-supplied DOM element
$container.append(renderer.domElement);

其实没那么难!

4. 网格

我们有场景、相机和渲染程序(我在示例代码中选择的是 WebGL ),但没有实际绘制的内容。Three.js 实际上支持加载几种不同的标准文件类型,如果您要输出 Blender、Maya、Cinema4D 或任何其他来源的模型,这会非常有用。简单起见(这毕竟是关于入门的!)我会说基元。原语是几何网格,是相对基本的网格,例如球体、平面、立方体和圆柱体。借助 Three.js,您可以轻松创建这些类型的基元:

// set up the sphere vars
var radius = 50, segments = 16, rings = 16;

// create a new mesh with sphere geometry -
// we will cover the sphereMaterial next!
var sphere = new THREE.Mesh(
new THREE.SphereGeometry(radius,
segments,
rings),

sphereMaterial);

// add the sphere to the scene
scene.add(sphere);

很好,但是球体的材质呢?在代码中,我们使用了变量 sphereMaterial,但尚未定义。首先,我们需要更详细地介绍一下“Material”

5. 材质

毫无疑问,这是 Three.js 最有用的部分之一。它为您提供了许多可应用于网格的常见(且非常方便)的材料:

  1. “基本”- 仅表示渲染为“非照亮”
  2. 兰伯特

还有更多,但为了简单起见,我会让您亲自探索一下。对于 WebGL 而言,尤其是这些材料可以救命。原因何在?在 WebGL 中,您必须为要渲染的所有内容编写着色器。着色器本身就是一个很大的话题,但简而言之,它们是用 GLSL(OpenGL 着色器语言)编写的,可以告诉 GPU 某些内容应该具有什么外观。这意味着您需要模拟光照、反射等数学运算。情况可能很快就会变得非常复杂。得益于 Three.js,您不必去做就好,可以不用再去费心,因为它为您省去了繁琐的工作。不过,如果您想编写着色器,也可以使用 MeshShaderMaterial 执行此操作,因此它是一种灵活的设置。

不过,现在我们可对球体应用弹性材料:

// create the sphere's material
var sphereMaterial = new THREE.MeshLambertMaterial(
{
// a gorgeous red.
color: 0xCC0000
});

另外值得注意的是,创建颜色之外的材质时,您还可以指定其他属性,例如平滑处理或环境映射。您应该查看 Wiki 页面,了解您可以在材料上设置的各种属性,实际上还包括引擎为您提供的任何对象。我们最近还发布了 threejs.org,以呈现更吸引人的 API 视图。

6. 灯光!

如果您现在渲染场景,您会看到一个红色圆圈。虽然我们应用了 Lambert 材料,但场景中没有光线,因此默认情况下 Three.js 会还原为完整的环境光,这与平铺着色相同。让我们通过一个简单的光点来解决这个问题:

// create a point light
var pointLight = new THREE.PointLight( 0xFFFFFF );

// set its position
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;

// add to the scene
scene.add(pointLight);

7. 渲染

值得注意的是,现在,我们已经完成所有设置,可以进行渲染了。但实际上我们需要继续执行以下操作:

// draw!
renderer.render(scene, camera);

不过,您可能需要多次渲染,因此如果要执行循环,应该真的使用 requestAnimationFrame;这是在浏览器中处理动画的最智能方式。它尚未获得完全支持,因此我强烈建议您参阅 Paul Irish 的 shim

8. 通用对象属性

如果您花些时间仔细查看 Three.js 的代码,您会看到许多对象从 Object3D“继承”。这是一个基础对象,其中包含一些非常有用的属性,如 positionrotationscale 信息。尤其是我们的球面是一个继承自 Object3D 的网格,并向其添加了自己的属性:几何图形materials。我为什么提到这些?您不太可能希望在屏幕上只展示一个球体而不执行任何操作,这些属性值得研究,因为它们允许您即时操纵网格和材料的基础细节。

// sphere geometry
sphere.geometry

// which contains the vertices and faces
sphere.geometry.vertices // an array
sphere.geometry.faces // also an array

// its position
sphere.position // has x, y and z properties
sphere.rotation // same
sphere.scale // ... same

9. 小秘密

我想简单介绍一下 Three.js 的小问题:例如,如果您修改网格的顶点,就会发现渲染循环中没有任何变化。原因何在?因为 Three.js(据我所知)缓存了网格数据,是一种优化。您实际上需要做的是向 Three.js 标记一些已经更改的内容,以便它可以重新计算所需的内容。为此,请使用以下代码:

// changes to the vertices
sphere.geometry.__dirtyVertices = true;

// changes to the normals
sphere.geometry.__dirtyNormals = true;

同样,我刚才说的还有很多,但我找到的那两个最有用。显然,您应该仅标记已更改的内容,以避免不必要的计算。

总结

希望这段对 Three.js 的简要介绍能对您有所帮助。真正亲力亲为;尝试各种事物,我无法高度推荐。在浏览器中原生运行 3D 的过程非常有趣,而使用 Three.js 这样的引擎可以为您消除许多麻烦,让您可以制作出一些非常酷的内容。为便于用户了解,我已经在这篇实验文章中总结了源代码,方便您参考。 如果您喜欢这方面的内容,请通过 Twitter 与我联系,我很乐意与您打招呼!