中文原文链接:http://www.21haolou.com/articles/show/140
英文原文链接:http://aerotwist.com/tutorials/getting-started-with-three-js/
Three.js的GitHub:https://github.com/mrdoob/three.js/
Three.js的官方演示站:http://mrdoob.github.com/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世界中,我们会涉及到下面这些概念,这些概念会伴随整个创作流程:
- 场景
- 渲染器
- 镜头
- 物体(带材质的)
当然,你可以制作一些疯狂的内容,而且我也希望这样干,并且在你自己的浏览器中开始实验。
兼容性
对于浏览器的支持情况,我在这里做一个快速简要说明。以我的经历来看,在对渲软引擎的支持及其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.z = 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最有用的部分。它提供了不少常见(而且非常方便)的材质可覆盖于网格曲面上
- "基本"材质 ——在无光情况下进行渲染
- Lambert材质
- 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.x = 10; pointLight.position.y = 50; pointLight.position.z = 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/