三、核心组件详解
3.1 几何体(Geometry / BufferGeometry)
几何体定义了物体的形状,它由顶点(vertices)和面(faces)组成。Three.js 提供了大量预置的几何体,方便快速构建基础形状。
Three.js 提供了丰富的内置几何体:
// 立方体
const boxGeometry = new THREE.BoxGeometry(2, 2, 2);
// 球体:半径1,宽度分段32,高度分段32
const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);
// 圆柱体:顶半径1,底半径1,高度2
const cylinderGeometry = new THREE.CylinderGeometry(1, 1, 2, 32);
// 圆锥体:底半径1,高度2
const coneGeometry = new THREE.ConeGeometry(1, 2, 32);
// 平面:宽4,高4
const planeGeometry = new THREE.PlaneGeometry(4, 4);
// 甜甜圈:半径1,管半径0.4
const torusGeometry = new THREE.TorusGeometry(1, 0.4, 16, 100);
当预置的几何体无法满足需求时,可以通过自定义顶点来创建任意形状:
// 创建自定义几何体 - 三角形
const geometry = new THREE.BufferGeometry();
// 定义顶点位置(3个顶点,每个顶点有x,y,z坐标)
const vertices = new Float32Array([
0, 1, 0, // 顶点1 (上)
-1, -1, 0, // 顶点2 (左下)
1, -1, 0 // 顶点3 (右下)
]);
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
// 定义面的颜色(可选)
const colors = new Float32Array([
1, 0, 0, // 红色
0, 1, 0, // 绿色
0, 0, 1 // 蓝色
]);
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
3.2 材质(Material)
材质决定了物体表面的外观,包括颜色、纹理、光泽度、透明度等属性。
// 标准材质(最常用)
const standardMaterial = new THREE.MeshStandardMaterial({
color: 0xff6600,
roughness: 0.3, // 粗糙度 0-1,值越小表面越光滑
metalness: 0.7, // 金属感 0-1,值越高越像金属
emissive: 0x000000,// 自发光颜色
emissiveIntensity: 0,
flatShading: false,// 是否使用平面着色(显示棱角)
side: THREE.FrontSide // 渲染哪一面:FrontSide(正面)、BackSide(背面)、DoubleSide(双面)
});
// 基础材质(不受光照影响)
const basicMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
// 使用纹理图片作为材质
const textureLoader = new THREE.TextureLoader();
const woodTexture = textureLoader.load('wood.jpg');
const woodMaterial = new THREE.MeshStandardMaterial({ map: woodTexture });
3.3 光源(Light)
光源照亮物体,产生真实的立体感和阴影效果。
// 环境光:均匀照亮
const ambientLight = new THREE.AmbientLight(0x404040, 0.6); // 颜色、强度
// 平行光:模拟太阳
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 10, 7);
directionalLight.castShadow = true;
// 配置阴影参数
directionalLight.shadow.mapSize.width = 1024;
directionalLight.shadow.mapSize.height = 1024;
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 20;
directionalLight.shadow.camera.left = -5;
directionalLight.shadow.camera.right = 5;
directionalLight.shadow.camera.top = 5;
directionalLight.shadow.camera.bottom = -5;
scene.add(directionalLight);
// 点光源:灯泡效果
const pointLight = new THREE.PointLight(0xff6600, 0.8);
pointLight.position.set(2, 3, 4);
pointLight.castShadow = true;
scene.add(pointLight);
// 聚光灯:舞台灯光效果
const spotLight = new THREE.SpotLight(0xffffff, 1);
spotLight.position.set(0, 5, 2);
spotLight.castShadow = true;
spotLight.angle = Math.PI / 4; // 光锥角度
spotLight.penumbra = 0.3; // 边缘柔和度
spotLight.distance = 20; // 照射距离
scene.add(spotLight);
3.4 相机(Camera)
相机决定了观察场景的视角和方式。
透视相机(PerspectiveCamera)是最常用的相机,模拟人眼视觉效果:
// 透视相机:视野角度FOV、宽高比、近平面、远平面
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(5, 5, 10);
camera.lookAt(0, 0, 0);
正交相机(OrthographicCamera)产生平行投影,无近大远小效果,常用于 2D 场景:
// 正交相机:左、右、上、下、近平面、远平面
const size = 5;
const camera = new THREE.OrthographicCamera(-size, size, size, -size, 0.1, 100);
camera.position.set(5, 5, 10);
camera.lookAt(0, 0, 0);
四、高级概念
4.1 纹理与贴图
纹理是将图像贴在物体表面,增强真实感的重要手段。
// 创建纹理加载器
const textureLoader = new THREE.TextureLoader();
// 加载基础颜色贴图
const colorMap = textureLoader.load('texture.jpg');
// 加载法线贴图(用于增加凹凸感)
const normalMap = textureLoader.load('normal.jpg');
// 加载高光贴图(控制反光区域)
const specularMap = textureLoader.load('specular.jpg');
// 加载环境遮挡贴图(控制阴影深度)
const aoMap = textureLoader.load('ao.jpg');
// 创建材质并应用纹理
const material = new THREE.MeshStandardMaterial({
map: colorMap,
normalMap: normalMap,
roughnessMap: specularMap,
aoMap: aoMap,
roughness: 0.5,
metalness: 0.6
});
4.2 动画系统
Three.js 提供了两种主要方式来实现动画:
直接修改物体属性(逐帧动画)
function animate() { // 平移 cube.position.x += 0.01; // 旋转 cube.rotation.y += 0.02; // 缩放 cube.scale.setScalar(1 + Math.sin(Date.now() * 0.002) * 0.1); requestAnimationFrame(animate); }- 使用 AnimationMixer(骨骼动画/复杂动画)
```
import { AnimationMixer } from 'three';
// 加载带动画的模型
const loader = new GLTFLoader();
loader.load('model.glb', (gltf) => {
const mixer = new AnimationMixer(gltf.scene);
const action = mixer.clipAction(gltf.animations[0]);
action.play();
function animate() {
mixer.update(0.016); // 约60fps更新一次
requestAnimationFrame(animate);
}
animate();
});
**4.3 模型加载**
Three.js 支持多种 3D 模型格式,最常用的是 glTF(GL Transmission Format),它是 Web 3D 模型的标准格式。
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
const loader = new GLTFLoader();
loader.load('model.glb',
(gltf) => {
// 模型加载成功
const model = gltf.scene;
model.scale.set(1, 1, 1);
model.position.set(0, 0, 0);
scene.add(model);
// 播放动画(如果模型包含动画)
if (gltf.animations.length) {
const mixer = new THREE.AnimationMixer(model);
gltf.animations.forEach((clip) => {
mixer.clipAction(clip).play();
});
}
},
(xhr) => {
// 加载进度
const percent = (xhr.loaded / xhr.total) * 100;
console.log(`模型加载进度: ${percent}%`);
},
(error) => {
// 加载失败
console.error('模型加载失败:', error);
}
);
**4.4 粒子系统**
粒子系统用于创建大量微小对象的效果,如星空、雪花、火花等。
// 创建粒子几何体
const particlesGeometry = new THREE.BufferGeometry();
const particleCount = 5000;
// 随机生成粒子位置
const positions = new Float32Array(particleCount 3);
for (let i = 0; i < particleCount; i++) {
positions[i3] = (Math.random() - 0.5) 200;
positions[i3+1] = (Math.random() - 0.5) 100;
positions[i3+2] = (Math.random() - 0.5) * 100;
}
particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
// 创建粒子材质
const particlesMaterial = new THREE.PointsMaterial({
color: 0x88aaff,
size: 0.2,
transparent: true,
opacity: 0.8,
blending: THREE.AdditiveBlending // 添加混合模式,产生发光效果
});
// 创建粒子系统
const particles = new THREE.Points(particlesGeometry, particlesMaterial);
scene.add(particles);
// 让粒子系统缓慢旋转
function animate() {
particles.rotation.y += 0.001;
particles.rotation.x += 0.0005;
requestAnimationFrame(animate);
}
**4.5 射线检测(Raycaster)**
射线检测用于实现点击选择物体、拾取交互等功能。
// 创建射线检测器
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
// 监听鼠标点击事件
window.addEventListener('click', (event) => {
// 计算鼠标位置归一化坐标(范围 -1 到 +1)
mouse.x = (event.clientX / renderer.domElement.clientWidth) 2 - 1;
mouse.y = -(event.clientY / renderer.domElement.clientHeight) 2 + 1;
// 通过相机和鼠标位置更新射线
raycaster.setFromCamera(mouse, camera);
// 检测与物体的交点
const intersects = raycaster.intersectObjects(objects);
if (intersects.length > 0) {
// 选中了第一个相交的物体
const selected = intersects[0].object;
console.log('选中物体:', selected);
// 高亮选中的物体
selected.material.emissive.setHex(0xff6600);
}
});
# 五、性能优化
**5.1 几何体合并**
对于大量静态物体,可以将它们的几何体合并成一个,减少绘制调用次数。
// 只需导入必要的组件,减少体积
import { BoxGeometry, MeshStandardMaterial, Mesh, Scene } from 'three';
**5.2 使用 BufferGeometry**
BufferGeometry 比 Geometry 性能更好,推荐使用。
**5.3 限制帧率**
对于不需要高帧率的应用,可以限制动画帧率以节省资源。
let lastTime = 0;
const fps = 30;
const interval = 1000 / fps;
function animate(currentTime) {
requestAnimationFrame(animate);
const delta = currentTime - lastTime;
if (delta < interval) return;
lastTime = currentTime - (delta % interval);
// 更新逻辑...
}
**5.4 阴影优化**
阴影计算开销较大,可以通过以下方式优化:
// 降低阴影贴图分辨率
directionalLight.shadow.mapSize.width = 512;
directionalLight.shadow.mapSize.height = 512;
// 限制阴影投射范围
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 12;
directionalLight.shadow.camera.left = -5;
directionalLight.shadow.camera.right = 5;
directionalLight.shadow.camera.top = 5;
directionalLight.shadow.camera.bottom = -5;
// 只为重要物体开启阴影
cube.castShadow = true; // 立方体投射阴影
plane.receiveShadow = true; // 平面接收阴影
**5.5 资源释放**
及时释放不需要的资源,防止内存泄漏:
// 释放几何体
geometry.dispose();
// 释放材质
material.dispose();
// 释放纹理
texture.dispose();
// 从场景中移除物体
scene.remove(object);
```
来源:
http://detxg.cn/