网页开发者工具箱:ThreeJS

这是关于所有网页开发者都应该在他们的工具箱中拥有的有用库的系列文章中的第二篇。文章旨在向您展示这些库的功能,并帮助您充分利用它们。第二篇文章专门介绍 ThreeJS 库。

简介

ThreeJS 是一个最初由 Ricardo Cabello Miguel(又名“Mr. Doob”)编写的库。

此库使 WebGL 对普通人来说触手可及。 WebGL 是一个功能强大的 API,用于操作 3D 环境。此 Web 技术由 Kronos 小组标准化,并且 Firefox、Chrome 和 Opera 现在将其作为 HTML canvas 标签的 3D 上下文来实现。WebGL 基本上是另一个标准的 Web 版本:OpenGL ES 2.0。因此,此 API 是一个“低级”API,需要超出网页设计师习惯范围的技能和知识。这就是 ThreeJS 发挥作用的地方。ThreeJS 使网页开发者无需了解底层 API 所需的所有知识,即可访问 WebGL 的强大功能。

基本用法

该库具有 许多示例的良好文档。您会注意到文档的某些部分尚未完成(随时提供帮助)。但是,该库和示例源代码结构良好,因此请随时阅读源代码。

尽管 ThreeJS 简化了许多操作,但您仍然需要熟悉一些基本的 3D 概念。基本上,ThreeJS 使用以下概念

  1. 场景:放置所有 3D 对象并以 3D 空间方式操作它们的场所。
  2. 相机:一个特殊的 3D 对象,用于定义渲染视角以及空间渲染类型(透视或等距)。
  3. 渲染器:负责使用场景和相机来渲染 3D 图像的对象。

在场景中,您将拥有多个 3D 对象,它们可以是以下类型

  • 网格:网格是由几何图形(对象的形状)和材质(颜色和纹理)组成的对象。
  • 光点:一个特殊的对象,用于定义光源以突出显示所有网格。
  • 相机,如上所述。

以下示例将在具有 id“myPlanet”的 HTML 元素中绘制一个简单的线框球体。

/**
 * First, let's prepare some context
 */

// The WIDTH of the scene to render
var __WIDTH__  = 400,

// The HEIGHT of the scene to render
    __HEIGHT__ = 400,

// The angle of the camera that will show the scene
// It is expressed in degrees
    __ANGLE__ = 45,

// The shortest distance the camera can see
    __NEAR__  = 1,

// The farthest distance the camera can see
    __FAR__   = 1000

// The basic hue used to color our object
    __HUE__   = 0;

/**
 * To render a 3D scene, ThreeJS needs 3 elements:
 * A scene where to put all the objects
 * A camera to manage the point of view
 * A renderer place to show the result
 */
var scene  = new THREE.Scene(),
    camera = new THREE.PerspectiveCamera(__ANGLE__,
                                         __WIDTH__ / __HEIGHT__,
                                         __NEAR__,
                                         __FAR__),
    renderer = new THREE.WebGLRenderer();

/**
 * Let's prepare the scene
 */

// Add the camera to the scene
scene.add(camera);

// As all objects, the camera is put at the
// 0,0,0 coordinate, let's pull it back a little
camera.position.z = 300;

// We need to define the size of the renderer
renderer.setSize(__WIDTH__, __HEIGHT__);

// Let's attach our rendering zone to our page
document.getElementById("myPlanet").appendChild(renderer.domElement);

/**
 * Now we are ready, we can start building our sphere
 * To do this, we need a mesh defined with:
 *  1. A geometry (a sphere)
 *  2. A material (a color that reacts to light)
 */
var geometry, material, mesh;

// First let's build our geometry
//
// There are other parameters, but you basically just
// need to define the radius of the sphere and the
// number of its vertical and horizontal divisions.
//
// The 2 last parameters determine the number of
// vertices that will be produced: The more vertices you use,
// the smoother the form; but it will be slower to render.
// Make a wise choice to balance the two.
geometry = new THREE.SphereGeometry( 100, 20, 20 );

// Then, prepare our material
var myMaterial = {
    wireframe : true,
    wireframeLinewidth : 2
}

// We just have to build the material now
material = new THREE.MeshPhongMaterial( myMaterial );

// Add some color to the material
material.color.setHSV(__HUE__, 1, 1);

// And we can build our the mesh
mesh = new THREE.Mesh( geometry, material );

// Let's add the mesh to the scene
scene.add( mesh );

/**
 * To be sure that we will see something,
 * we need to add some light to the scene
 */

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

// and set its position
pointLight.position.x = -100;
pointLight.position.y = 100;
pointLight.position.z = 400;

// Now, we can add it to the scene
scene.add( pointLight );


// And finally, it's time to see the result
renderer.render( scene, camera );

如果您想对它进行动画处理(例如,使球体旋转),方法非常简单

function animate() {
    // beware, you'll maybe need a shim
    // to use requestAnimationFrame properly
    requestAnimationFrame( animate );

    // First, rotate the sphere
    mesh.rotation.y -= 0.003;

    // Then render the scene
    renderer.render( scene, camera );
}

animate();

JSFiddle 演示.

高级用法

掌握了基础知识后,ThreeJS 为您提供了一些高级工具。

渲染系统

作为抽象层,ThreeJS 提供了除 WebGL 之外的其他渲染场景选项。您可以使用 Canvas 2D API 以及 SVG 来执行渲染。这些渲染上下文之间存在一些差异。最明显的是性能。由于 WebGL 是硬件加速的,因此使用它渲染复杂的场景的速度惊人地快。另一方面,由于 WebGL 并非总是能很好地处理抗锯齿,因此如果您想要执行一些单元着色(卡通风格)操作,SVG 或 Canvas2D 渲染可能更好。作为一项特殊优势,SVG 渲染为您提供了对象的完整 DOM 树,如果您想要访问这些对象,这将非常有用。它在性能方面的成本可能很高(尤其是在对场景进行动画处理时),但它使您不必重建 完整的保留模式图形 API

网格和粒子

ThreeJS 非常适合在 WebGL 之上进行渲染,但它不是创作工具。要建模 3D 对象,您可以选择 3D 软件。方便的是,ThreeJS 附带了许多脚本,可以轻松地从多个来源导入网格(示例包括:Blender、3DSMax 或广泛支持的 OBJ 格式)。

还可以轻松部署粒子系统,以及使用雾、矩阵和自定义着色器。ThreeJS 还附带了一些预制材质:Basic、Face、Lambert、Normal 和 Phong)。WebGL 开发人员可以利用该库在库之上构建自己的材质,该库提供了一些非常好的助手。显然,构建这种自定义内容需要非常特殊的技能。

对网格进行动画处理

如果使用 requestAnimationFrame 是对场景进行动画处理的最简单方法,ThreeJS 提供了几个有用的工具来单独对网格进行动画处理:一个完整的 API 用于定义如何对网格进行动画处理,以及使用“骨骼”来变形和更改网格的能力。

限制和注意事项

ThreeJS 最大的限制之一与 WebGL 相关。如果您想使用它来渲染场景,您会受到此技术的限制。您会变得依赖硬件。所有声称支持 WebGL 的浏览器在硬件支持方面都有严格的要求。如果某些浏览器未在适当的硬件上运行,则它们将不会渲染任何内容。避免出现问题的最佳方法是使用诸如 modernizr 之类的库,根据每个浏览器的功能在渲染系统之间进行切换。但是,在使用非 WebGL 渲染系统时要小心,因为它们的功能有限(例如,Phong 材质仅在 WebGL 上下文中受支持)并且速度慢得多。

就浏览器支持而言,ThreeJS 支持所有支持 WebGL、Canvas2D 或 SVG 的浏览器,这意味着:Firefox 3.6+、Chrome 9+、Opera 11+、Safari 5+,甚至 Internet Explorer 9+(如果您不使用 WebGL 渲染模式)。如果您想依赖 WebGL,支持范围更小:仅限 Firefox 4+、Chrome 9+、Opera 12+、Safari 5.1+。您可以忘记 Internet Explorer(甚至即将推出的 IE10)以及当前可用的几乎所有移动浏览器。

结论

ThreeJS 极大地简化了直接在浏览器中生成 3D 图像的过程。它使您可以使用易于使用的 API 创建令人惊叹的视觉效果。它赋予您能力,让您可以释放您的创造力。

总之,以下是一些 ThreeJS 的酷炫用法

关于 Jeremie Patonnier

Jeremie 是 Mozilla 开发者网络的长期贡献者/员工,自 2000 年以来一直是专业网页开发者。他倡导 Web 标准,编写文档并创建各种关于 Web 技术的内容,旨在使 Web 技术对每个人都触手可及。

Jeremie Patonnier 的更多文章……


4 条评论

  1. Slim

    另一个酷炫的 webgl 用法。它几天前发布了。

    http://www.chaostoperfection.com

    2012 年 6 月 14 日 下午 4:21

    1. Jeremie Patonnier

      一个非常棒的演示,但由于非常讨厌的浏览器 UA 嗅探,无法使用 Firefox 观看它(T_T)。

      2012 年 6 月 14 日 上午 10:13

  2. Slim

    确实,当时没有在 Firefox 上尝试过。这真的很糟糕 :(

    2012 年 6 月 18 日 上午 6:35

  3. Stormgate

    我认为是时候开始搞 webgl 了,像这样的库使它变得如此易于访问,我知道如果我开始使用它,我最终会花一星期时间来制作东西!

    2012 年 6 月 25 日 上午 7:42

本文的评论已关闭。