组件 |
描述 |
相机 | 决定哪些东西将要在屏幕上渲染 |
光源 | 它们会对材质如何显示,以及生成阴影时材质如何使用产生影响 |
物体 | 它们是在相机透视图里主要的渲染对象:方块、球体等 |
var scene = new THREE.Scene(); //创建场景对象
//创建相机
var camera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 30;
camera.lookAt(scene.position);
//创建物体
var planeGeometry = new THREE.PlaneGeometry(60,40,1,1);
var planeMaterial = new THREE.MeshLambertMaterial({color:0xffffff});
var plane = new THREE.Mesh(planeGeometry,planeMaterial);
plane.rotation.x = -0.5 * Math.PI;
plane.position.x = 0;
plane.position.y = 0;
plane.position.z = 0;
scene.add(plane);
//添加环境光
var ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);
//添加点光源
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-40, 60, -10);
scene.add(spotLight);
效果图如下
addCube(添加方块)
this.addCube = function(){
var cubeSize = Math.ceil((Math.random()*3));
var cubeGeometry = new THREE.CubeGeometry(cubeSize,cubeSize,cubeSize);
var cubeMaterial = new THREE.MeshLambertMaterial({color:Math.random()*0xffffff});
var cube = new THREE.Mesh(cubeGeometry,cubeMaterial);
cube.castShadow = true;
cube.name = "cube-" + scene.children.length;
cube.position.x = -30 + Math.round((Math.random() * planeGeometry.parameters.width));
cube.position.y = Math.round((Math.random() * 5));
cube.position.z = -20 + Math.round((Math.random() * planeGeometry.parameters.height));
scene.add(cube);
this.numberOfObjects = scene.children.length;
}
注:1.name属性为方块指定了名字,可以用来在场景中查找对象,例如使用Scene.getChildByName(name)函数可直接获取指定 的对象;
2.Scene.children():获取场景中所有子对象的列表。
removeCube(移除最后一个添加的方块)
this.removeCube = function(){
var allChildren = scene.children;
var lastObject = allChildren[allChildren.length-1];
if(lastObject instanceof THREE.Mesh){
scene.remove(lastObject);
this.numberOfObjects = scene.children.length;
}
}
render循环渲染场景
var render = function () {
stats.update();
scene.traverse(function(e){
if (e instanceof THREE.Mesh && e != plane) {
e.rotation.x += controls.rotationSpeed;
e.rotation.y += controls.rotationSpeed;
e.rotation.z += controls.rotationSpeed;
}
})
requestAnimationFrame( render ); //周期性渲染
renderer.render( scene, camera );
};
注:traverse()函数所传递来的函数会在场景的每一个子对象上调用一次。
效果图如下
通过fog属性可以为整个场景添加雾化效果,即一个物体离得越远,就越模糊。在Three.js库里打开雾化效果很简单。只要在定义完场景后加上如下一行代码即可:
scene.fog = new THREE.Fog(0xffffff,0.015,100);
这段代码中我们定义了白色的雾化效果(0xffffff)。后面的两个属性用来调节雾的显示,0.015是near(近处)属性的值,而100设置的是far(远处)属性的值。
打开雾化后的效果图如下
当我们像下面这段代码一样使用overrideMaterial属性即材质覆盖属性时,所有添加到场景中的物体都会使用同样的材质:
scene.overrideMaterial = new THREE.MeshLambertMaterial({color:0xffffff});
函数/属性 |
描述 |
add(object) | 在场景中添加对象。 |
children | 返回一个场景中所有对象的列表,包括相机和光源。 |
getChildByName(name) | 创建对象时,可以通过name属性为它指定一个独一无二的名字。场景对象提供了一个办法,你可以使用该方法根据名字直接返回这个对象。 |
remove(object) | 如果你在场景中引用了一个对象,那么你也可以用这个函数在场景中删除它。 |
traverse(function) | children属性返回场景中所有子对象的列表。通过traverse()函数,我们同样可以传入一个回调函数访问这些子对象。 |
fog | 通过该属性可以设置场景的雾化效果。 |
overrideMaterial | 通过这个属性,你可以强制场景中的所有物体都使用相同的 材质。 |
在创建几何体时,我们既可以使用Three.js中提供的几何体,也可以通过定义顶点和面,手工创建几何体,可参考以下代码:
var vertices = [
new THREE.Vector3(1,3,1),
new THREE.Vector3(1,3,-1),
new THREE.Vector3(1,-1,1),
new THREE.Vector3(1,-1,-1),
new THREE.Vector3(-1,3,-1),
new THREE.Vector3(-1,3,1),
new THREE.Vector3(-1,-1,-1),
new THREE.Vector3(-1,-1,1)
];
var faces = [
new THREE.Face3(0,2,1),
new THREE.Face3(2,3,1),
new THREE.Face3(4,6,5),
new THREE.Face3(6,7,5),
new THREE.Face3(4,5,1),
new THREE.Face3(5,0,1),
new THREE.Face3(7,6,2),
new THREE.Face3(6,3,2),
new THREE.Face3(5,7,0),
new THREE.Face3(7,2,0),
new THREE.Face3(1,3,4),
new THREE.Face3(3,6,4)
];
var geom = new THREE.Geometry();
geom.vertices = vertices;
geom.faces = faces;
geom.computeFaceNormals();
我们在创建网格的时候,可以为一个几何体使用多种材质,例如,我们想显示一个绿色透明的方块的同时还想显示线框,可使用以下代码:
var materials = [
new THREE.MeshBasicMaterial({color: 0x000000, wireframe: true}),
new THREE.MeshLambertMaterial({opacity: 0.6, color: 0x44ff44, transparent: true})
];
var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, materials);
mesh.castShadow = true;
mesh.children.forEach(function (e) {e.castShadow = true});//为组中所有对象添加阴影
效果图如下:
这里,我们先总结一些基本属性和函数
函数/属性 |
描述 |
position(位置) | 决定该对象相对其父对象的位置。多数情况下,一个对象的父对象是THREE.Scene()对象。 |
rotation(旋转) | 通过这个属性你可以设置对象绕任何一个轴的旋转弧度 |
scale(比例) | 通过这个属性你可以沿着x,y和z轴缩放对象 |
translateX(amount)(X轴平移) | 沿x轴将对象平移指定的距离 |
translateY(amount)(Y轴平移) | 沿y轴将对象平移指定的距离 |
translateZ(amount)(Z轴平移) | 沿z轴将对象平移指定的距离 |
我们可以用三种方式设置对象的位置
//直接设置坐标
cube.position.x = 10;
cube.position.y = 3;
cube.position.z = 1;
//一次性设置
cube.position.set(10,3,1);
//设置数组
cube.position = new THREE.Vector3(10,3,1);
我们也可以用三种方式旋转对象
//直接设置坐标
cube.rotation.x = 10;
//一次性设置
cube.rotation.set(0.5*Math.PI,0,0);
//设置数组
cube.rotation = new THREE.Vector3(0.5*Math.PI,0,0);
我们可以使用下面的方法沿轴缩放物体
cube.scaleX = 1;
cube.scaleY = 1;
cube.scaleZ = 1;
使用translate函数可以改变对象的位置,但不是定义将对象放在哪里的绝对位置,而是定义相对偏移量。
使用透视相机,使得距离相机越远的方块,被渲染得越小。如下图所示:
THREE.PerspectiveCamera接受如下这些参数:
参数 |
描述 |
fov(视场) | fov表示视场(field of view)。这是从相机位置能够所能够看到的部分场景。 但是由于普通的计算机显示器不能完全显示我们看到的景象,所以一般会选择一块儿较小的区域。 推荐默认值:45 |
aspect(长宽比) | 这是渲染结果输出区的横向长度和纵向长度的比值。 推荐默认值:window.innerWidth/window.innerHeight |
near(近面) | near属性定义的是Three.js库从距离相机多近的地方开始渲染场景。通常情况下我们会为这个属性设一个很小的值,从而可以渲染从相机位置可以看到的所有物体。 推荐默认值:0.1 |
far(远面) | far属性定义的是相机可以从它所在的位置看多远。如果我们将这个值设得太低,那么场景中的一部分可能就不会被渲染;如果设得太高,在某些情况下会影响渲染的效率。 推荐默认值:1000 |
使用正投影相机,所欲的方块渲染出来的尺寸都一样,如下图所示:
THREE.OrthographicCamera接受如下这些参数:
参数 |
描述 |
left(左边界) | 在Three.js文档里该属性是可视范围的左边界。 |
right(右边界) | 可视范围的右边界。比这个右侧边界更的对象不会被渲染。 |
top(上边界) | 可被渲染空间的最上面 |
bottom(下边界) | 可被渲染空间的最下面 |
near(近面) | 基于相机所在的位置,从这一点开始渲染场景 |
far(远面) | 基于相机所在的位置,一直渲染到场景中的这一点 |