Three-js 创建第一个3D场景
1.一个场景至少需要的三种类型组件
相机/决定哪些东西将在屏幕上渲染
光源/他们会对材质如何显示,以及生成阴影时材质如何使用产生影响
物体/他们是在相机透视图里主要的渲染队形:方块、球体等
2.浏览器兼容
Moziller Firefox:4.0版本以后开始支持;
Google Chrome:第9版以后开始支持
Safari:5.1版本开始支持;
Opera:12.00版本以后开始支持。要让Opera支持WebGL,你还需要打开opera:config文件,设置WebGL,并将Enable hardare Acceleration设置为1;
Inernet Explorer:从IE11开始支持WebGL
如果想让旧版本IE支持WebGL,可以使用iewebgl插件,下载网址是http://iewebgl.com/。
3.材质
Three.js里有两种材质对光源产生反应:MeshLambertMaterial和MashPhongMaterial。
4.添加阴影
添加阴影必须指定几个步骤。首先需要让渲染器支持阴影:
render.shadowMapEabled = true; // render为WebGLRenderer对象
其次需要设置哪些物体作为阴影源,哪些物体作为接受阴影:
plane.receiveShadow = true; // plane平面接受阴影 cube.castShadow = true; // cube立方体产生阴影 sphere.castshadow = true; // sphere球体产生阴影
最后需要置顶哪些光源可产生投影:
spotLight.castShadow = true // spotLight光源可产生阴影
5.检测动画帧频插件state.js
Three.js作者也写了一个显示每秒帧数(FPS)的插件,可用来统计渲染。首先在页面引入state.js文件。然后创建一个检测显示的div:
<div id="State-output"></div>
写一个初始化统计函数:
function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; }
在创建渲染对象时,我们也初始化state:
var state = initState();
在执行渲染的动画函数中,每次执行时都调用下state的update函数:
function render() { stats.update(); ... requestAnimationFrame(render); renderer.render(scene, camera); }
6.使用dat.GUI库简化试验
Google几个人创建了一个名为dat.GUI的库,使用它,你很容易就可以创建一个简单的界面组件,用以修改代码中的变量。例如我们可以实时修改球体的弹跳速度,方块的旋转速度等等。
就像添加其他对象一样,首先需要引入dat.gui.js,接下来需要一定一个javascript对象,保存想通过dat.GUI库修改的那些变量,也可以绑定函数而调用对象函数。如定义一个controls对象:
var controls = new function(){ this.rotationSpeed = 0.02; this.bouncingSpeed = 0.03; }
定义了两个属性,以及设置了默认值。接下来把这个对象传递给dat.GUI对象,并定义两个属性的取值范围,如下所示:
(function(){ ... var gui = new dat.GUI(); gui.add(controls, 'rotationSpeed', 0, 0.5); gui.add(controls, 'bouncingSpeed', 0, 0.5); ... });
现在要做的是保证在render循环里直接饮用这两个属性。这样当我们在dat.GUI界面修改时可直接影响物体的旋转速度和弹跳速度。
function render(){ ... cube.rotation.x += controls.rotationSpeed; cube.rotation.y += controls.rotationSpeed; cube.rotation.z += controls.rotationSpeed; step += controls.bouncingSpeed; sphere.position.x = 20 + (10 * (Math.cos(step))); sphere.position.y = 2 + (10 * Math.abs(Math.sin(step))); ... requestAnimationFrame(render); }
运行界面,在界面右上角可看到定义的两个属性,我们可以实时修改属性,查看界面动画效果。
7.Three.Scene常用函数和属性
scene.add(object):添加一个对象到场景对象汇总。包括Sphere、Box、Cube、Light等。
scene.remove(object):从Scene中删除一个对象
scene.getChildByName(name):通过名称获取Scene下的对象,名称可通过例如cube.name = 'cube-1'这种方式指定。
scene.children():获取场景中的所有子对象列表
scene.traverse(function(e){}):遍历scene下的子对象。我们可以通过例如e instaceof THREE.Mesh来判断类型进行过滤
scene.fog:通过该属性设置场景的雾化效果。它可以渲染出一层雾气,隐藏远处的物体
scene.overrideMaterial:通过这个属性,你可以强制场景中的所有物体使用同一个材质
8.雾化效果
three.js添加雾化效果很简单,第一种方式:
//new THREE.Fog(color, near, far) scene.fog = new THREE.Fog(0xffffff, 0.015, 100);
包含三个参数,第一个参数color指定雾化颜色,第二个参数near指定近点位置,第三个far参数指定远点位置。第二种方式:
scene.fog = new THREE.FogExp2(0xffffff, 0.015);
这种方式不指定near和far属性,只给颜色和浓度。浓度也就是雾化因子,雾化因子也是通过near和far算出来的。
9.动态修改物体的顶点
three.js假设一个网格的几何体在其生命周期内不会改变。为了支持动态修改顶点坐标。我们需要在渲染的时候添加下面的代码:
mesh.children.forEach(function(e){ e.geometry.vertices = vertices; e.geometry.verticesNeedUpdate = true; e.geometry.computeFaceNormals(); });
verticesNeedUpdate属性指定顶点需要重新渲染,computeFaceNormals指定Face需要重新渲染。
10.网格Mesh常用函数和属性
position(位置)/决定该对象相对其父对象的位置。多数情况下,一个对象的父对象是THREE.Scene()对象
rotation(旋转)/通过这个属性你可以设置对象绕任何一个轴旋转弧度
scale(比例)/通过这个属性可以沿着x、y、z轴缩放对象
translateX(amout)/沿x轴将对象平移指定的距离。如果是负数则沿着x轴负方向
translateY(amout)/沿y轴将对象平移指定的举例。如果是负数则沿着y轴负方向
translateZ(amout)/沿z轴将对象平移指定的举例。如果是负数则沿着z轴负方向
11.正投影相机和透视投影相机
three.js提供了两种相机:THREE.PerspectiveCamera(透视投影相机)和THREE.OrthographicCamera(正投影相机)。首先看PerspectiveCamera构造函数new THREE.PerspectiveCamera(fov, aspect, near, far)参数:
fov/fov表示视场。这是从相机位置能够看到的部分场景。推荐默认值为45
aspect/长宽比,这是渲染结果输出区的横向长度和纵向长度的比值。默认推荐window.innerWidth/window.innerHeight。
near/近面,near属性定义的是three.js库从距离相机多斤的地方开始渲染场景。默认值推荐为0.1。
far/远面,far属性定义的而是相机可以从它所处的位置看多远。默认值推荐为1000.
正投影相机构造函数new THREE.OrthographicCamera(left, right, top, bottom, near, far)的参数:
left/左边界;right/右边界;top/上边界;bottom/下边界;near/近边界;far远边界。
创建了相机之后,我们需要指定聚集点的位置:
camera.lookAt(new THREE.Vector3(x, y, z));
12.Canvas Renderer和WebGL Renderer区别
HTML5 canvas renderer和WebGL renderer主要区别是,HTML5 canvas渲染器直接使用javascript在canvas上绘制3D场景。这种方式最主要的问题是糟糕的表现。而使用THREE.WebGLRenderer,我们可以通过硬件加速执行渲染。但THREE.CanvasRenderer对象,我们不得不完全依赖软件渲染,这导致了低性能呈现。另外一个缺点是,THREE.CanvasRenderer不能使用three.js提供的高级材质,而只有WebGL才可以使用。