# 总体概览
# 基础渲染
# 创建一个canvas画布
# 创建场景-scene
定义:添加3D对象的地方,在实际开发中场景是透明的、看不见的,需要做相关的设置
作用
Scene 对象是所有不同对象的容器,也就是说该对象保存所有物体、光源、摄像机以及渲染所需的其他对象。
Scene 对象又是被称为场景图,它不仅仅是一个对象数组,还包含了整个场景图树形结构中的所有节点:
* 每个添加到 Three.js 场景的对象,甚至包括 THREE.Scene 本身都是继承自一个名为 THREE.Object3D 的对象。
* 每个 THREE.Object3D 对象也可以有自己的子对象,我们可以使用它的子对象来创建一个 Three.js 能解释和渲染的对象树。
1
2
3
4
2
3
4
常用方法及属性
add(object): 用于向场景中添加对象。使用该方法还可以创建对象组。
children:用于返回一个场景中所有对象的列表,包括摄像机和光源。
getObjectByName(name,recursive):在创建对象时可以指定唯一的标识 name,使用该方法可以查找特定名字的对象。
* 当参数 recursive 设置为 false 时,在调用者子元素上查找
* 当参数 recursive 设置为 true 时,在调用者的所有后代对象上查找
remove(object): object 为场景中对象的引用,使用该方法可以将对象从场景中移除。
traverse(function):该方法也可以遍历调用者和调用者的所有后代,function 参数是一个函数,被调用者和每一个后代对象调用 function 方法。
fog :使用该属性可以为场景添加雾化效果,可以产生隐藏远处物体的浓雾效果。
overrideMaterial:使用该属性可以强制场景中的所有物体使用相同的材质。
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
scene场景的结构
group
group
mesh
line
point
group
mesh
line
point
group
group
mesh
line
point
group
mesh
line
point
light
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 光源
光源的类型
环境光(AmbientLight)
该光源没有特定的方向,不会产生阴影。
点光源(PointLight)
一个向各个方向发光的光源从一个点发出。
定向光(DirectionalLight)
发出的所有光线彼此平行,太阳就是一个很好的例子。
聚光灯(SpotLight)
最常使用的灯之一(尤其是如果您想要使用阴影),THREE.SpotLight是一种具有锥形效果的光源,你可以将其与手电筒或灯笼进行比较,这种光有方向和角度它产生光。
半球光(HemisphereLight )
区域光(AreaLight)
镜头光晕(LensFlare)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
创建光源
1.创建光源
2.设置光源的位置
3.打开或者关闭阴影
4.将光源添加进入场景
1
2
3
4
2
3
4
# 相机-camera
相机的类型:
1.正交相机orthographic:在这种投影模式下,渲染图像中的对象大小保持不变,无论其与相机的距离如何。这对于渲染 2D 场景和 UI 元素等非常有用。
2.透视相机perspective:这种投影模式旨在模仿人眼看到的方式。它是用于渲染 3D 场景的最常见的投影模式。
1
2
2
创建相机
1.创建相机(PerspectiveCamera)
2.设置相机的位置
3.设置相机以那个方向为上方
4.设置相机看向那个坐标
5.将相机添加进入场景
1
2
3
4
5
2
3
4
5
# 创建渲染器-renderer(WebGLRenderer)
# 模型
几何体
缓冲类几何体(BufferGeometry)
长方体(BoxGeometry)
圆柱体、圆锥、三面体、四面体(梯形)(CircleGeometry)
圆锥体(ConeGeometry)
球体(SphereGeometry)
立方体边框(BoxHelper)
入参:模型和颜色
边框不需要进行设定位置,会自动在模型边上进行吸附
圆柱体、梯形边框(EdgesGeometry)
let cubeGeometry = new THREE.CylinderGeometry((80, 80, 50, 40, 40) // 创建一个圆柱材质
let cylinderEdges = new THREE.EdgesGeometry(cubeGeometry, 1); // 创建一个圆柱边框
let edgesMtl = new THREE.LineBasicMaterial({ color: ‘red’}) // 创建基础线条材质
let border = new THREE.LineSegments(cylinderEdges, edgesMtl); // 创建线框
cube.add(border ); // 将线框加入几何体中
不规则模型(Shape)
先使用Shape创建一个不规则平面(使用点到点连线)
再将平面加厚则可以得到一个不规则模型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
创建模型mesh
1.创建几何体
2.创建材质
3.设置几何体位置
4.添加进入场景scene
1
2
3
4
2
3
4
引入模型
three.js
可以引入的模型格式有以下几种:gltf、obj、stl、FBX(没试过),推荐使用gltf格式,gltf格式的模型可以进行压缩,体积更小,加载更快。
// 引入模型
loadFenceModel(options = {}) {
return new Promise(resolve => {
let { path, length, width, height } = options
// gltf格式
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('/gltf/') // public/gltf
dracoLoader.preload()
const loader = new GLTFLoader()
loader.setDRACOLoader(dracoLoader)
loader.load(path, (gltf) => {
gltf.scene.traverse((object, index) => {
// if (object.isMesh) { // 调整模型中心点
// object.applyMatrix4(new THREE.Matrix4().makeTranslation(0, 0, 0))
// }
})
const carMesh = gltf.scene
carMesh.name = 'car-mesh'
// carMesh.scale.set(50, 50, 50)
carMesh.scale.set(length, width, height)
carMesh.position.set(0, 0, 0)
// console.log(carMesh);
// console.log(this, 'this');
this.scene.add(carMesh)
resolve()
})
// obj格式
// const objLoader = new OBJLoader()
// objLoader.load(path, (object) => {
// console.log(object, '9999')
// console.log(this, '00000')
// object.castShadow = true
// object.receiveShadow = true
// object.scale.set(50, 50, 50)
// object.position.set(0, 0, 0)
// this.scene.add(object)
// resolve()
// })
// stl格式
// const stlLoader = new STLLoader()
// stlLoader.load(path, (geometry) => {
// const material = new THREE.MeshPhongMaterial({ color: 0xff5533, specular: 0x111111, shininess: 200 });
// const mesh = new THREE.Mesh(geometry, material)
// mesh.scale.set(0.2, 0.2, 0.2)
// mesh.position.set(0, 0, 0)
// this.scene.add(mesh)
// resolve()
// })
})
}
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
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
# 边框
给模型添加边框的两种方式
// 方法一:
let cubeGeometry = new THREE.BoxGeometry(100, 80, 90)
let cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
let cubeMaterial = new THREE.MeshLambertMaterial({ color: 'red' })
// 将需要的参数加入group中
group.add(cube)
let border = new THREE.BoxHelper(cube, 'red')
group.add(border)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
注意1:用这种方法,只适合与立方体
注意2:用这种方法,比如我要旋转立方体,边框不会跟着改变。
// 方法二:
let cubeGeometry = new THREE.CylinderGeometry((80, 80, 50, 40, 40) // 创建一个圆柱材质
let cylinderEdges = new THREE.EdgesGeometry(cubeGeometry, 1); // 创建一个圆柱边框
let edgesMtl = new THREE.LineBasicMaterial({ color: 'red'}) // 创建基础线条材质
let border = new THREE.LineSegments(cylinderEdges, edgesMtl); // 创建线框
cube.add(border ); // 将线框加入几何体中
1
2
3
4
5
6
2
3
4
5
6
注意:用这种方法,比如我要旋转立方体,边框会跟着改变。
# 功能
# 模型拖动
鼠标拖动DragControls属性
dragstart:开始移动
drag:移动中
dragend:结束移动
hoveron:移动鼠标在模型上
hoveroff:移动鼠标离开模型
1
2
3
4
5
2
3
4
5
键盘按键移动
addEventListener()
1
创建模型拖动
1.创建模型拖动对象(DragControls)
传入mesh集合、相机对象、渲染器对象
2.创建拖动事件
可以改变拖动颜色,获取拖动后的坐标等等
1
2
3
4
5
2
3
4
5
# 碰撞检测(Raycaste、Box3)
Raycaste():在物体的各个顶点发出射线,计算是否和其他物体相交。
Box3():在物体上创建包围盒,计算两个物体包围盒是否相交。
1.创建当前拖动的mesh为meshA
let meshA = new THREE.Box3(new THREE.Vector3(), new THREE.Vector3())
2.循环其他需要参与碰撞检测的mesh
3.创建循环体内将每一个mesh为meshB
let meshB= new THREE.Box3(new THREE.Vector3(), new THREE.Vector3())
4.判断meshA是否与meshB重合(meshA.intersectsBox(meshB))
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
注意:碰撞检测,检测的是最外层mesh
# 视角切换
补间动画(TWEEN.Tween): 让视角切换更平滑
设置相机位置(position.set)
# 模型贴图
贴canvas(CanvasTexture)
- 创建一个canvas元素
- 作为一个参数传入THREE.CanvasTexture
- 贴图纹理更新texture.needsUpdate = true
贴图片TextureLoader()
var texture = new THREE.TextureLoader().load('/favico.ico')
texture.wrapS = THREE.RepeatWrapping
texture.wrapT = THREE.RepeatWrapping
meshParamsNo.map = texture
1
2
3
4
2
3
4
# 智能装箱功能
# 创建字体(TextGeometry)
- 创建字体对象(FontLoader)
- 引入字体json文件
- 创建文字几何图形(TextGeometry)
- 创建文字的正面和侧面集合(MeshPhongMaterial)
- 创建一个mesh模型将文字几何图形和文字集合放入其中
- 将mesh模型加入场景中
# 创建三维坐标轴(AxesHelper)
- 创建三维坐标系
- 创建好坐标系将其加入场景中
# 创建线条(Line)
- 创建材质(LineBasicMaterial)
- 创建空间几何体(BufferGeometry)
- 创建顶点集合(Vector3)
- 绑定顶点到创建好的空间几何体(setFromPoints)
- 创建线条(Line)
- 将线条添加进场景中
# 创建控件对象(OrbitControls)
- 创建控件对象(OrbitControls)
- 修改鼠标控制事件
- 上下滚动鼠标中键:缩放三维场景
- 鼠标左键:720旋转展示三维场景
- 鼠标右键:可以平移三维场景(关闭)
# 优化
注意:避免重复创建模型对象,可以使用clone()方法
- clone()返回一个新的几何体对象,返回新的几何体对象包含原来的几何体顶点数据、顶点索引数据、UV坐标数据。
- threejs中的clone方法是一个浅度的clone,clone复制了新的对象,但是原对象内部的对象(属性为对象)不会被clone,我们需要对内部对象也进行clone就可以
常见问题
- 在用copy()和clone()进行对象复制后,使用Raycaster射线做obj模型选择时,使用clone方式选择指定对象对其颜色进行增强,但是修改新对象的material原皮肤也变更。
- 在使用模型拖动的时候,当前页面/场景会出现卡顿现象,这是因为模型拖动的过程中,会不断的进行渲染,导致页面卡顿,可以使用requestAnimationFrame()方法来降低场景渲染帧率进行优化。
← vscode常用插件 Three性能优化 →