【Three】Three.js入门之相机

有两种相机

  • 近交投影
  • 正交投影

近交投影

和真实世界中我们所看到的物体一样, 近大远小
近交投影

透视投影照相机

THREE.PerspectiveCamera(fov, aspect, near, far)

透视投影照相机

  • fov —- 视野宽度
  • aspect —- 长宽比, 推荐使用 window.innerWidth / window.innerHeight
  • near —- 近裁面, 推荐值 0.1
  • far —- 远裁面, 推荐值 1000, 值太大影响性能, 值太小场景显示不全

正交投影

建模类软件使用的比较多

正交投影就像老师在黑板上画的立方体,保证三维世界平行的线到了二维世界也是平行的, 不存在近大远小的概念,

正交投影相机

THREE.OrthographicCamera(left, right, top, bottom, near, far) // near far决定远近范围

  • left —- 左边界
  • right —- 右边界
  • top —- 上边界
  • bottom —- 下边界
  • near —- 近裁面
  • far —- 远裁面
  • camera.lookAt —- 设置目标点

在Three中, 创建正交投影相机的参数决定了所看到的视景体, 视景体内部的物体才能显示在屏幕上,视景体外部的就会被裁剪掉

图中灰色区域就是视景体
正交投影相机

摄影机效果比对

说概念总是比较抽象, 我们来实际操作一下,

大概思路就是, 首先将立方体铺满平面, 然后我们使用定时器来切换相机类型 , 以此来区别出两种相机的效果

第一步—-将立方体铺满平面

利用我们之前设定的面的宽高, 计算出一列应该有多少立方体, 一行应该有多少立方体, 然后将其排列好, 添加入场景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 将立方体铺满屏幕
var cubeGeometry = new THREE.BoxGeometry(4,4,4)
for ( var j=0; j < planeGeometry.parameters.height / 5 ;j++) { // 面高 50
for ( var i=0; i < planeGeometry.parameters.width / 5 ; i++) { // 面宽 70
// 随机生成
var rnd = Math.random() * 0.75 + 0.25
// 添加材质
var cubeMaterial = new THREE.MeshLambertMaterial()
// 添加颜色
cubeMaterial.color = new THREE.Color(rnd, 0, 0)
// 创建立方体
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
// 设置立方体的位置
cube.position.x = -(planeGeometry.parameters.width / 2) + 2 +(i * 5)
cube.position.y = 2
cube.position.z = -(planeGeometry.parameters.height / 2) + 2 +(j * 5)
// 立方体加入场景
scene.add(cube)
}
}

第二步—-用键盘控制相机角度

每当按下左右键时, 就调整相机的y 轴方向的旋转角度, 然后重新绘制场景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 绑定键盘事件
document.onkeydown = function(e) {
switch(e.keyCode) {
case 37:
camera.rotation.y += 0.02
render()
break;
case 39:
camera.rotation.y -= 0.02
render()
break;
}
}
function render() {
renderer.render(scene, camera)
}
render()

第三步—-利用定时器切换摄像机的模式

利用定时器切换 相机的模式,然后就会在下次一用户按下键盘时被渲染出来

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
// 用于切换相机模式
var controls = new function () {
this.perspective = "Perspective"
this.switchCamera = function () {
if( camera instanceof THREE.PerspectiveCamera ) {
console.log('Orthographic')
this.perspective = 'Orthographic'
camera = new THREE.OrthographicCamera (
window.innerWidth / -16,
window.innerWidth / 16,
window.innerHeight / -16,
window.innerHeight / 16,
-200,
500
)
camera.position.x = -20
camera.position.y = 60
camera.position.z = 50
camera.lookAt(scene.position)
}else {
console.log('Perspective')
this.perspective = "Perspective"
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.x = -20
camera.position.y = 60
camera.position.z = 50
camera.lookAt(scene.position)
}
}
}
// 切换相机模式
setInterval(() => {
controls.switchCamera()
}, 2000)

查看效果

随着我不断地按下键盘的方向键, 画布被重新渲染, 我们可以看到两种相机的不同效果在来回切换

两种摄影机模式

完整代码

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第一个ThreeJs</title>
</head>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
<body>
</body>
<script src="../three.js"></script>
<!-- 游戏帧率辅助库 -->
<script src="../stats.min.js"></script>
<script src="../SceneUtils.js"></script>
<script>
// 设置场景,
var scene = new THREE.Scene();
// 设置相机 视角, 宽度/高度, 近距离点, 远距点
var camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.x = -30
camera.position.y = 40
camera.position.z = 10
camera.lookAt(scene.position) // 看向场景的中央


// 设置绘制对象---基于Webgl的渲染器
var renderer = new THREE.WebGLRenderer()
renderer.setClearColor(new THREE.Color(0xeeeeee));
// 控制渲染尺寸
renderer.setSize(window.innerWidth, window.innerHeight)
// 打开阴影
renderer.shadowMapEnabled = true


// 设置辅助测试工具
var axes = new THREE.AxisHelper(20)
scene.add(axes)

// 设置平面
var planeGeometry = new THREE.PlaneGeometry(70, 50, 1, 1) //设置宽高和段度
var planeMaterial = new THREE.MeshLambertMaterial({color: 0xcccccc}) // 设置颜色
var plane = new THREE.Mesh(planeGeometry, planeMaterial)
// 设置旋转角度
plane.rotation.x = -0.5 * Math.PI;
// 设置坐标
plane.position.x = 15
plane.position.y = 0
plane.position.z = 0

plane.receiveShadow = true
// 加入场景
scene.add(plane)


/*
*
* 添加材质和灯光
*
* */

// 设置点光源

var spotLight = new THREE.SpotLight(0xffffff);
// 设置位置
spotLight.position.set(-40, 60, -10)
spotLight.castShadow = true
// 添加进点光源
scene.add(spotLight)

// --------------------------关键区域-----------------------------------------

// 将立方体铺满屏幕
var cubeGeometry = new THREE.BoxGeometry(4,4,4)
for ( var j=0; j < planeGeometry.parameters.height / 5 ;j++) { // 面高 50
for ( var i=0; i < planeGeometry.parameters.width / 5 ; i++) { // 面宽 70
// 随机生成
var rnd = Math.random() * 0.75 + 0.25
// 添加材质
var cubeMaterial = new THREE.MeshLambertMaterial()
// 添加颜色
cubeMaterial.color = new THREE.Color(rnd, 0, 0)
// 创建立方体
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
// 设置立方体的位置
cube.position.x = -(planeGeometry.parameters.width / 2) + 2 +(i * 5)
cube.position.y = 2
cube.position.z = -(planeGeometry.parameters.height / 2) + 2 +(j * 5)
// 立方体加入场景
scene.add(cube)
}
}
// 用于切换相机模式
var controls = new function () {
this.perspective = "Perspective"
this.switchCamera = function () {
if( camera instanceof THREE.PerspectiveCamera ) {
console.log('Orthographic')
this.perspective = 'Orthographic'
camera = new THREE.OrthographicCamera (
window.innerWidth / -16,
window.innerWidth / 16,
window.innerHeight / -16,
window.innerHeight / 16,
-200,
500
)
camera.position.x = -20
camera.position.y = 60
camera.position.z = 50
camera.lookAt(scene.position)
}else {
console.log('Perspective')
this.perspective = "Perspective"
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.x = -20
camera.position.y = 60
camera.position.z = 50
camera.lookAt(scene.position)
}
}
}
// 切换相机模式
setInterval(() => {
controls.switchCamera()
}, 2000)


// 绑定键盘事件
document.onkeydown = function(e) {
switch(e.keyCode) {
case 37:
camera.rotation.y += 0.02
render()
break;
case 39:
camera.rotation.y -= 0.02
render()
break;
}
}
function render() {
renderer.render(scene, camera)
}
render()

// --------------------------关键区域-----------------------------------------


// 将renderer的输出挂到 body
document.body.appendChild(renderer.domElement)


</script>
</html>
你的支持将鼓励我继续创作