three.js 3D效果

Three js入门教程

Three.js在处理浏览器3D效果方面表现优异。通过Three js,你可以创建镜头,物体,光线,材质等。

介绍

在自己的一些实验性项目中运用了Three.js,它在处理浏览器3D效果方面表现优异。通过Three js,你可以创建镜头(Cameras),物体(objects),光线(lights),材质(materials)等等,你还可以选择渲染器:可以使用HTML5的Canvas来绘制场景,也可选择使用WebGL或是SVG来渲染。另外它还是开源的,因而若有兴趣的话,你也可参与到Three js项目中来。不过,这里主要是讲讲我自己从使用该3D引擎中学到的一些东西,并介绍一些基本内容。

尽管Three js有种种好处,但是你也可能不时会碰到纠结之处。一个典型的情况就是你需要耗费大量时间研究他人实例,做逆向工程,搜寻具体的函数,偶尔还需通过GitHub需求帮助。顺便提一下,如果你的确需要寻求帮助,Mr. doob 和 AlteredQualia这两个地方会帮上你大忙的。

基础

这里,我默认读者已经了解基本的3D概念,并具精通JavaScript技能。如果你没有上述基础,我建议你在接触Three js之前最好学习一下,不然后面你会碰到些疑惑的。

在3D世界中,我们会涉及到下面这些概念,这些概念会伴随整个创作流程:

  1. 场景
  2. 渲染器
  3. 镜头
  4. 物体(带材质的)

当然,你可以制作一些疯狂的内容,而且我也希望这样干,并且在你自己的浏览器中开始实验。

兼容性

对于浏览器的支持情况,我在这里做一个快速简要说明。以我的经历来看,在对渲软引擎的支持及其JavaScript引擎的速度方面,Google的Chrome浏览器做的最好。Chrome支持Canvas,WebGL以及SVG,且速度极快。Firefox的表现位居第二,其JavaScript引擎速度要比Chrome稍许慢些,但是对渲软器的支持依旧不错,而且新版本JavaScript引擎速度越来越快。Opera还正在增加对WebGL的支持,而Mac上的Safari浏览器提供了启用WebGL的选项。因此,基本上Opera和Safar只支持Canvas渲软,了解这点很重要。目前IE9也只支持Canvas渲染,而且我也尚未听说微软有任何支持WebGL的消息。在目前阶段,微软似乎不会考虑WebGL。

设置场景

这里我假设你选用了支持所有渲染引擎的浏览器,你希望使用Canvas或是WebGL来渲染,因为这两个是更为标准的技术。Canvas得到的支持程度要好于WebGL,这里值得一提的是,WebGL是调用的显卡的GPU,这样CPU的话就主要负责其他非渲染类的任务,像物理引擎或用户交互方面的任务。

不管你选用何种引擎,你应牢记JavasScript需要为性能优化,毕竟对浏览器而言,3D运算不是项轻松的内容(能实现就已经很牛B了)。因此需要清楚的了解自身代码的瓶颈之处,如有可能,消灭这些瓶颈代码。

假设你已经下载并将three js包含在你的HTML文件中,那么我们如何设置场景(scene)呢?见下面例子

// 设置场景大小
var WIDTH = 400,
  HEIGHT = 300;

// 设置镜头属性
var VIEW_ANGLE = 45,
  ASPECT = WIDTH / HEIGHT,
  NEAR = 0.1,
  FAR = 10000;

// 获取绑定的DOM元素,假设我们使用的jQuery处理。
var $container = $('#container');

// 创建WebGL渲染器,镜头以及场景
var renderer = new THREE.WebGLRenderer();
var camera =
  new THREE.PerspectiveCamera(
    VIEW_ANGLE,
    ASPECT,
    NEAR,
    FAR);

var scene = new THREE.Scene();

// 在场景中添加镜头
scene.add(camera);

// 镜头起始位置0,0,0,因此将镜头回拉
camera.position.= 300;

// 开始渲染
renderer.setSize(WIDTH, HEIGHT);

//增添渲染器提供的DOM元素
$container.append(renderer.domElement);

创建网格曲面

现在创建好一个场景,一个镜头以及一个渲染器(在上述示例中,我选用WebGL做渲染),但是我们还尚未绘制任何内容。Three js实际上还支持部分不同标准的文件类型。如果你有模型需要从Blender,Maya或是Cinema4D导入的,这点特性就显得非常不错。为了简单起见,我讲讲基本物体(primitive)。基本物体是几何网格曲面,或是像球体,平面,立方体和圆柱体这类相对简单的物体。Three js可以让你轻松地创建上述类型的基本物体。

//设置球体变量
var radius = 50,
    segments = 16,
    rings = 16;

// 使用球体几何创建新的网格曲面,接下来我会覆盖上球体材质。
var sphere = new THREE.Mesh(

  new THREE.SphereGeometry(
    radius,
    segments,
    rings),

  sphereMaterial);

// 在场景中添加球体。
scene.add(sphere);

嗯,一切完好,但是球体的材质如何添加呢?在代码中,我们使用了球体材质的变量(sphereMaterial),但是尚未定义,接下来,我们需要更详细的了解下材质方面的内容。

材质

毋庸置疑,这部分内容是Three js最有用的部分。它提供了不少常见(而且非常方便)的材质可覆盖于网格曲面上

  1. "基本"材质 ——在无光情况下进行渲染
  2. Lambert材质
  3. Phong材质 

除此之外还有其他材质,但是为简单起见,读者可自行摸索。在WebGL中,这些材质可是救命的功能。为什么呢?因为在WebGL中,你必须得为所有需要渲染的东西编写着色器(Shader),而着色器本身就是一个庞杂的话题,简单说来,着色器使用GLSL(OpenGL Shader Language)写成。它告诉GPU如何渲染物体的外观。这意味着你需要对光线,反射等等进行模拟。其内容会变得极为复杂。幸亏有了Three js,你不用处理这部分内容。但如果你想自己编写着色器的话,那么你也可以用MeshShaderMaterial来实现,因此它的设置相对灵活。

接下来,我们可对球体运用lambert材质

// 创建球体的材质
var sphereMaterial =new THREE.MeshLambertMaterial({
      color: 0xCC0000
    });

这里值得一提是,除了颜色,你在创建材质时还可以指定其他属性,比如,顺滑度或环境贴图。对于引擎提供的其他物体以及材质的可设置属性选项,你可以访问这个维基页面查看。

光线

如果你现在就开始渲染场景的话,你只会看到一个红色的圆。虽然我们已经添加了Lambert材质,但是场景中默认是没有光源的。Three js就会归位为全环境光,其等同于表面颜色。我们可以指定一点光源来解决这个问题。

// 创建点光源
var pointLight =new THREE.PointLight(0xFFFFFF);

// 设置光源位置
pointLight.position.= 10;
pointLight.position.= 50;
pointLight.position.= 130;

// 添加至场景
scene.add(pointLight);

渲染循环

所有渲染所需东西已经准备就绪。但实际上我们还需要继续做下面这项工作:

//绘图
renderer.render(scene, camera);

你渲染的次数可能不止一次,所以你需循环渲染,你最好使用requestAnimationFrame来做。它会非常智能的处理浏览器中的动画问题。但是目前还尚未得到完全支持,因此强烈推荐你了解下Paul Irish这篇内容。

一般物体的属性

如果你有时间阅读Three js的代码,你会发现许多物体继承自Object3D。这一以及基本的对象,包含一些非常有用的属性,比如位置, 旋度缩放比例等信息。我们的球体就是一个继承自Object3D的网格曲面,不过它增添了自身特有的一些属性:几何材质。为什么我要提这些呢?你不可能只想在屏幕上显示一个啥都不能干的球体。这些属性非常值得研究,因为它可以让你随时操控网格曲面的细节之处。

// 球形几何体
sphere.geometry

// 包含的顶点及面。
sphere.geometry.vertices // 一个数组
sphere.geometry.faces // 也是一个数组

// 位置
sphere.position // 包含X,Y,Z
sphere.rotation // 同上
sphere.scale // 同上

小提示

使用Three js时,有一点需要了解:如果你修改网格曲面的顶点时,你注意到在循环渲染中,并没有发生任何变化。为什么?原因就是Three js为了优化性能起见,对网格曲面的数据进行了缓存。这时你需要告诉three js,内容已经发生改动,以便three js重新进行计算。如下:

// 将几何体设置为动态,允许更新
sphere.geometry.dynamic = true;

// 对顶点的改动
sphere.geometry.__dirtyVertices = true;

// 对法线(normals)的改动
sphere.geometry.__dirtyNormals = true;

使用Three js需要注意的不止这点,但是我发现这点最需要注意,你应只标记已做改动的内容,避免无谓的计算。

结论

这里,我希望这篇对three js的简单入门介绍能够帮你。实践出真知,我强烈建议你动手实践。在浏览器中跑3D乐趣不少,而使用three js这样的引擎可为你免掉不少麻烦,使你专注于创造。

为了方便起见,我将这篇文章中涉及的源代码压缩打包了,供你参考。

原文:http://aerotwist.com/tutorials/getting-started-with-three-js/

posted @ 2013-02-21 12:43  CatherineGao  阅读(1879)  评论(0编辑  收藏  举报