Skip to content
世界坐标辅助器 -- AxesHelper
************************
javascript
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

轨道控制器 -- OrbitControls
可以旋转角度查看模型,需要配合自动渲染动画使用,一直更新。
javascript
// 需要单独引入
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
const controls = new OrbitControls(camera, renderer.domElement);
// 设置带阻尼 (滑动带有渐停)
controls.enableDamping = true;
// 设置阻尼系数
controls.dampingFactor = 0.05;
// 设置自动旋转
controls.autoRotate = true;

// 添加动画
function animate() {
  requestAnimationFrame(animate);
  cube.rotation.x += 0.01;
  // 轨道控制器更新  必须在animate中调用
  controls.update();
  renderer.render(scene, camera);
}
animate();
场景属性 -- Scene
添加背景 **scene.background** = 图片 || 颜色

添加雾(效果)Fog

javascript
// 添加背景颜色
scene.background = new THREE.Color(0x666666);
// 添加背景图片 
scene.background = new THREE.CubeTextureLoader().setPath('/').load(['2.jpg', '2.jpg', '2.jpg', '2.jpg', '2.jpg', '2.jpg']);

// 添加雾
scene.fog = new THREE.Fog(0xcccccc, 10, 15);
透视相机 -- PerspectiveCamera
**fov**,****![](https://cdn.nlark.com/yuque/0/2024/png/33655561/1730778326681-9fab8dc4-342b-43cd-95da-8e208ea619ac.png)

视锥体近端面,远端面;

近1远10,视锥体效果图

lookAt(cube.position),相机的视野方向,眼球除了位置还有方向概念;

相机在高处平视看不到,降低视野,俯视几何体

gui调试器
用于在网页上快速调试,需要单独下载dat.gui插件

使用步骤:

1.先创建一个控制属性对象

javascript
// 创建一个控制对象
const controlData = {
  rotationSpeed: 0.01,  // 转速
  color: 0x00ff00,
  wireframe: false,
  envMap: '无'
}

2.new一个gui对象实例

javascript
const gui = new dat.GUI()

3.添加配置

html
const f = gui.addFolder('配置') // 创建一个设置分组
f.add(controlData, 'rotationSpeed').min(0.01).max(0.1).step(0.01).name('旋转速度') // 最小值,最大值,步长
// 颜色选择器
f.addColor(controlData, 'color').name('颜色')
// 下拉列表
f.add(controlData, 'envMap', ['无', '环境贴图1', '环境贴图2']).name('环境贴图')
// checkbox
f.add(controlData, 'wireframe').name('线框')

f.open() // 默认展开

4.具体实现

原理就是在animate动画中设置网格cube的各种属性,属性值就等于配置对象中的值,这样只要属性值以改变,几何体也就一起改变。注意color接受的时 THREE.Color的包裹值,不能直接赋值16进制数值

vue
function animate() {
    requestAnimationFrame(animate);
    // cube.rotation.x += 0.05;
    // cube.rotation.y += 0.05;

    // 绑定为gui调试器的值
    cube.rotation.x += controlData.rotationSpeed;
    cube.rotation.y += controlData.rotationSpeed;

    cube.material.color = new THREE.Color(controlData.color);
    material.wireframe = controlData.wireframe;

    // 轨道控制器更新  必须在animate中调用
    controls.update();
    renderer.render(scene, camera);
  }
材质贴图和环境贴图 -- TextureLoader -- CubeTextureLoader
:::info 几何体呈现的样式,涂鸦由材质决定,材质分为很多种,都有公用的一些属性和自己的单独属性,如下为基础网格材质的属性 --** 贴图**,贴图所需要的值为**纹理(Texture);**

:::

TextureLoader,平面贴图,用于在几何体身上使用,使几何体更加真实

vue
创建纹理 -- 平面贴图
const texture = new THREE.TextureLoader().load("/texture/1mp.jpg");
const material = new THREE.MeshBasicMaterial({ 
    color: 0x00ff00,
    map: texture
});

通过添加纹理贴图,对比单一颜色更为真实

CubeTextureLoader立体纹理,多用于环境贴图,通过6个不同的环境面,模拟真实的空间,顺序为 左右上下前后。

vue
创建立体纹理 -- 左右上下前后
const cubeTexture = new THREE.CubeTextureLoader().setPath("/texture/").load([
  "04.jpg", "01.jpg",
  "05.jpg", "02.jpg",
  "06.jpg", "03.jpg",
]) 
scene.background = cubeTexture

通过6个面拼接

基础网格材质除了map这种颜色贴图,也支持envMap环境贴图,将环境贴图的属性赋值给球状几何体,可以模拟出反射的状态; 效果图如上;

vue
创建球体
const geometry = new THREE.SphereGeometry(1);
const material = new THREE.MeshBasicMaterial({ 
  envMap: cubeTexture
});
自定义几何图形 -- BufferGeometry
在创建几何体时,可以通过官方提供的一些常见的几何体快捷的创建,但是除了这些我们也可以自定义去创建几何体,几何体的面都是由多个**三角形**拼接而成的,所以每**三个坐标**就代表**一个顶点**,**x,y,z**;

创建方式一:直接描述所有顶点****

javascript
const geometry = new THREE.BufferGeometry();
// 创建一个简单的矩形. 在这里我们左上和右下顶点被复制了两次。
// 因为在两个三角面片里,这两个顶点都需要被用到。 x,y,z
const vertices = new Float32Array( [
  -1.0, -1.0,  1.0, 
  1.0, -1.0,  1.0,
  1.0,  1.0,  1.0,
  1.0,  1.0,  1.0,
  -1.0,  1.0,  1.0,
  -1.0, -1.0,  1.0
] );

// itemSize = 3 因为每个顶点都是一个三元组。
geometry.setAttribute('position', new THREE.BufferAttribute( vertices, 3 ) );

创建方式一这样写虽然说也可以实现,但是会有几个点是重合的,我们可以省略他们。

创建方式二:使用顶点索引方式创建,在已有的Float32Array数组中,直接使用索引生成,最后设置给geometry的index属性

tsx
// 需要确认几何体的顶点
// 利用索引来确定几何体的绘制方式
const indices = new Uint16Array([
  0, 1, 2, 2, 3, 0
])

geometry.setIndex(new THREE.BufferAttribute(indices, 1));
自定义UV值 -- Float32Array
创建网格材质的map为纹理对象时texture时,默认的显示位置是通过uv值决定的,可以自定义

灯光的变化 -- AmbientLight
![](https://cdn.nlark.com/yuque/0/2024/png/33655561/1732786865495-a5853033-db9c-4a53-b1b2-2c11f3dcffb9.png)

在之前的例子中,使用的材质都是基础网格材质,是不受光源影响的;当使用高光反射材质时,物体就会受到灯光的影响,所以没有灯光的情况下,物体渲染出来就是漆黑的,看不到自身的颜色。当在场景中添加上环境光后(),物体就会可见

没环境光之前 有环境光

vue
const ambientLight = new THREE.AmbientLight(0xffffff, 1); // 光颜色 光照强度
scene.add(ambientLight);

光有环境光还不是很真实,添加一个点灯光,模拟自然中的太阳,灯泡.。。。

在添加点灯光后,需要手动开启灯光投射阴影,pointLight.castShadow = true; // 灯光将投射阴影,然后给几何体也开启投射阴影,这样在光照处就可以有阴影的显示了

在场景中添加一个点灯光

javascript
const pointLight = new THREE.PointLight(0xffffff, 100, 100);
pointLight.position.set( 2, 3, 5 );
pointLight.castShadow = true; // 灯光将投射阴影
scene.add( pointLight );
// 添加灯光辅助
const lightHelper = new THREE.PointLightHelper(pointLight, 0.1);
scene.add(lightHelper);
Object3d和分组 -- Vector3 -- Group
在**三维空间中**,所有物体都有**自己**的**三维向量**Vector3(**x, y, z**),对于物体坐标可以使用创建的三维向量来进行赋值,实际场景中物体的移动应该是靠改变该变量而实现的。
javascript
const vector = new THREE.Vector3(1, 1, 1);
// 之前修改
// cube.position.set(1, 1, 1);
// cube.position.x = 1
// 通过三维向量修改
cube.position.add(vector)

Object3d:
cube.position.addScalar(1) // 在当前的坐标位置基础上+1

cube.position.clone() // 当前坐标位置

cube.translateX(1); // 局部平移

cube.visible = true; // 是否可见

cube.scale.set(2, 1, 1); // 局部缩放


分组:正常是直接创建一个网格添加到场景中,分组是先创建两个网格,都有各自的OBject3D属性,然后创建一个组,将两个网格添加到组中,最后将组添加到场景中,组也有自己的Object3D属性

java
// 物体1
const cubeA = new THREE.Mesh( geometry, material );
// 设置物体1的位置
cubeA.position.set( 1, 1, 1 );
// 物体2
const cubeB = new THREE.Mesh( geometry, material );
cubeB.position.set( -1, -1, -1 );

// 创建组
const group = new THREE.Group();
// 设置组的位置
group.position.set(2, 0, 0);
// 组add物体1
group.add( cubeA );
group.add( cubeB );
// 场景加组
scene.add( group );

组向x移动,物体也跟着移动

欧拉角度 -- Euler

blender基本使用
+ 按住滚轮可以拖动视角 + shift+滚轮可以移动物体 + s+滚轮放大缩小 + ~操作相机 + 左上角箭头可以设置视图 + 导出模型格式 + .fbx: + .obj: 游戏用,可编辑 + .glb/gltf: web浏览器用
GLTE模型加载器 -- GLTFLoader
在实际开发中,threejs提供的简单几何体无法满足需求,需要通过建模软件来制作成品,我们直接使用,GLTFLoader就是用来在three中引入这些3D模型的;**需要注意所有3D模型引入进来都是黑的,需要灯光才能显示**

tsx
const loader = new GLTFLoader();
loader.load('/src/assets/01.glb', function (gltf) {
  console.log(gltf, 'gltf');
  gltf.scene.traverse((child) => {
    // 遍历模型中的物体
    if (child.name == '柱体') {
      child.material = material;
      child.castShadow = true; // 开启阴影
    }
    // 接收投影(立方体)
    if( child.name == '立方体' ){
      child.receiveShadow = true;
      child.position.y = -1.5;
    }
  })
  scene.add(gltf.scene);
})

总体逻辑就是在场景中引入外部3D模型,然后GLTFLoader实例对象中load方法的第二个参数回调函数中的参数中有我们整个模型的信息,通过名字判断其中模型的具体内容,来进行操作设置每一个模型都是一个普通的Mesh对象