效果预览:效果预览
源码下载:关注公众号【RMRF】,回复【three5】可获取源码
一、安装
npm install three
1
二、App.vue
<template>
<div class="index">
<div id="container"></div>
</div>
</template>
<script>
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
export default {
data() {
return {
scene: null, // 场景
camera: null, // 相机
renderer: null, // 渲染器
composer: null, // 效果合成器
lightHelper: null
};
},
mounted() {
this.init();
},
methods: {
// 初始化
init() {
const el = document.getElementById('container');
this.initScene();
this.initCamera();
this.initRenderer(el);
this.initCube();
this.initPlane()
this.initOrbitControls();
this.initSpotLight()
this.render();
window.addEventListener('resize', this.onWindowResize);
},
// 场景
initScene() {
this.scene = new THREE.Scene();
},
// 相机
initCamera() {
this.camera = new THREE.PerspectiveCamera(
35,
window.innerWidth / window.innerHeight,
1,
2000
);
this.camera.position.set(46, 22, -21);
},
// 渲染器
initRenderer(el) {
this.renderer = new THREE.WebGLRenderer({
antialias: true
});
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.renderer.shadowMap.enabled = true;
el.appendChild(this.renderer.domElement);
},
// 缩放
initOrbitControls() {
let controls = new OrbitControls(this.camera, this.renderer.domElement);
controls.target.set(0, 7, 0);
controls.maxPolarAngle = Math.PI / 2;
controls.update();
},
// 渲染
render() {
this.renderer.render(this.scene, this.camera);
if (this.lightHelper) {
this.lightHelper.update()
}
requestAnimationFrame(this.render);
},
// 自适应
onWindowResize() {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
},
// 立方体
initCube() {
const geometry = new THREE.BoxGeometry(3, 3, 3);
const material = new THREE.MeshPhongMaterial();
let cube = new THREE.Mesh(geometry, material);
cube.castShadow = true;
cube.receiveShadow = true;
this.scene.add(cube);
},
// 地板
initPlane() {
let geometry = new THREE.PlaneGeometry(50, 50);
let material = new THREE.MeshPhongMaterial({
color: 0xffffff,
dithering: true
})
let mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0, -3, 0);
// 沿着X轴旋转
mesh.rotation.x = -Math.PI * 0.5;
// 接受阴影
mesh.receiveShadow = true;
this.scene.add(mesh);
},
// 聚光灯
initSpotLight() {
const light = new THREE.SpotLight(0xffff00, 1)
// 投射阴影
light.castShadow = true
// 光照最大范围
light.angle = 0.4
// 半影衰减百分比
light.penumbra = 0.2
// 沿着光照距离的衰减量
light.decay = 2
// 光照最大距离
light.distance = 50
// 位置
light.position.set(0, 20, 13)
this.scene.add(light)
// 光照锥形辅助
this.lightHelper = new THREE.SpotLightHelper(light);
this.scene.add(this.lightHelper)
// 环境光
const ambientLight = new THREE.AmbientLight(0x404040);
this.scene.add(ambientLight);
}
}
};
</script>
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
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