Three.js教程(3):场景

场景(Scene)相当于是一个容器,可以在它上面添加光线,物体等,最后Three.js把它和相机一起渲染到DOM中。


Three.js中的坐标系

在开始本章的时候我们需要先了解一下Three.js中的坐标系。Three.js的坐标系如下:

坐标系

由上,我们可知Three.js中的坐标系X轴是水平朝右的,Y轴是垂直朝上的,Z轴垂直与屏幕朝向我们,这与CSS中的坐标系的不同点在于,CSS的Y轴是垂直朝下的。下面给一个例子,可以供你更好的了解Three.js中的坐标系,请务必自己运行一下这个例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
var camera, scene, renderer;
var geometry, material, mesh;
var stats = new Stats();
var gui = new dat.GUI();
var obj = {
x : 0,
y : 0,
z : 0,
rotateX : 0,
rotateY : 0,
rotateZ : 0
};

function init() {
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.z = 5;

scene = new THREE.Scene();
geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
material = new THREE.MeshLambertMaterial();
mesh = new THREE.Mesh( geometry, material );
mesh.receiveShadow = true;
scene.add( mesh );

renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3+: custom
document.body.appendChild( stats.dom );

gui.add(obj, 'x', -3, 3);
gui.add(obj, 'y', -3, 3);
gui.add(obj, 'z', -3, 3);
gui.add(obj, 'rotateX', 0, 360);
gui.add(obj, 'rotateY', 0, 360);
gui.add(obj, 'rotateZ', 0, 360);
}

function animate() {
stats.update();

requestAnimationFrame( animate );
mesh.position.x = obj.x;
mesh.position.y = obj.y;
mesh.position.z = obj.z;
// 需要把角度修改为弧度
mesh.rotation.x = obj.rotateX / 180 * Math.PI;
mesh.rotation.y = obj.rotateY / 180 * Math.PI;
mesh.rotation.z = obj.rotateZ / 180 * Math.PI;
renderer.render( scene, camera );
}

init();
animate();

效果图如下,你可以自己调一下参数:

效果图

场景的属性和方法

创建场景很简单:

1
var scene = new THREE.Scene();

对于他的属性和方法也不是很多:

类型 名称 描述 默认值
属性 fog 场景中雾的效果 null
属性 overrideMaterial 覆盖材质,如果有这个那么场景中物体的材质会被覆盖 null
属性 autoUpdate 自动更新 true
属性 background 背景 null
方法 toJSON() 把场景转换为JSON对象,可以供Three.js导入场景使用 -
方法 dispose() 清楚缓存数据 -

THREE.Scene的属性并不多,你可能会问,之前把Mesh添加到Scene中使用到了一个add方法怎么没写?确实场景是有这个方法的,更准确的说这个方法是来自它的父类THREE.Object3D的,它是好多Three.js对象的直接或间接父类,所以了解它的属性和方法非常有必要,由于篇幅有限,这里就不再叙述了,你可以在这里看一看。

背景设置

根据上面的API设置背景的话就非常简单了:

1
scene.background = new THREE.Color('orange');

效果如下:
效果图

注意这里必须是Color对象(而不是字符串的值,或者16进制的数字)。这里我们遇到了一个新的对象叫Color,该对象的参数表示什么颜色,主要有这么几种格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 颜色的关键字
var color = new THREE.Color('orange');

// 默认背景,白色的 注意Three.js渲染的默认背景是黑色的
var color = new THREE.Color();

// 十六进制数字
var color = new THREE.Color( 0xff0000 );

// RGB字符串
var color = new THREE.Color("rgb(255, 0, 0)");
var color = new THREE.Color("rgb(100%, 0%, 0%)");

// HSL字符串
var color = new THREE.Color("hsl(0, 100%, 50%)");

// RGB的值 取值范围0~1 如红色:
var color = new THREE.Color( 1, 0, 0 );

除了直接使用scene.background外还有另外一种设置背景颜色的方法是,就是设置清屏的颜色:

1
renderer.setClearColor(new THREE.Color(0xff0000));

两者之前scene.background的优先级会更高一些,因为scane相当于是在清屏的背景之上再绘制了一层。

雾化效果

我们现在使用的是MeshNormalMaterial这个材质,要使用雾化效果和光线效果,那么需要MeshLambertMaterial或者MeshPhongMaterial这两种材质,具体的细节我们后面讨论。现在我们先把材质换成MeshLambertMaterial,然后做下面修改看看雾化效果:

1
scene.fog = new THREE.Fog(0xffffff, 0.1, 10);

具体的效果需要手动修改z轴看来不同浓雾下物块的样子,效果如下:

近处效果图
远处效果图

这里需要注意一下我们的物块是黑色的即使修改材质MeshLambertMaterial的颜色也是黑色的,因为目前还没有添加光线。

上面我们使用了Fog对象,他的构造函数有3个参数,分别是颜色、雾的起始距离,雾的结束距离Fog对象出来的雾是线性增长的,Three.js还提供了一种指数增长的雾是FogExp2,它有两个参数分别是颜色和浓度,可以如下设置:

1
scene.fog = new THREE.FogExp2(0xffffff, 0.01);

设置统一的材质

设置场景中所有物体的材质,其实是很简单的,如:

1
scene.overrideMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});

由于我们目前还没有加入光线,所以现在看不了效果,这个例子先不做演示,只要记得有个方法可以设置就行了,到时候自己查一下基本上OK。

-------------本文结束 感谢您的阅读-------------
0%