一、Three.js 2026 最新特性概述
根据官方文档,2026 年 Three.js 迎来了多项重要更新,特别是在 WebGPU 渲染器、PBR 材质和阴影系统方面的改进:
- WebGPU 渲染器增强:WebGPURenderer 的阴影效果得到显著提升,可能需要调整阴影偏移值以减少阴影瑕疵。
- PBR 材质改进:粗糙材质(roughness > 0.5)的能量守恒计算更加精确,视觉上会比之前版本稍亮。
- PMREM 反射优化:环境贴图反射效果更真实,特别是在复杂光照环境下。
- API 变更:RGBELoader 已更名为 HDRLoader,RGBMLoader 被移除,推荐使用 EXRLoader 或 UltraHDRLoader。
二、GLTF 模型导入基础
1. GLTF 格式优势
GLTF(GL Transmission Format)是 Three.js 推荐的标准模型格式,具有以下优势:
- 体积小,适合网络传输
- 支持材质、动画、骨骼等完整特性
- 加载速度快,渲染效率高
- 二进制格式(.glb)打包所有资源,部署方便
2. 基本导入代码
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
// 1. 创建场景
const scene = new THREE.Scene();
// 2. 初始化加载器
const loader = new GLTFLoader();
// 3. 加载模型
loader.load(
'path/to/your/model.gltf',
(gltf) => {
// 4. 将模型添加到场景
scene.add(gltf.scene);
// 可选:打印模型结构
console.log(gltf.scene);
},
(progress) => {
// 加载进度回调
console.log(`加载进度: ${(progress.loaded / progress.total * 100).toFixed(2)}%`);
},
(error) => {
// 错误处理
console.error('模型加载失败:', error);
}
);
三、模型居中的三种实现方式
方法一:通过包围盒计算中心点
function centerModel(model) {
// 更新模型的世界矩阵
model.updateMatrixWorld();
// 创建包围盒并计算模型边界
const box = new THREE.Box3().setFromObject(model);
// 获取包围盒中心点
const center = box.getCenter(new THREE.Vector3());
// 调整模型位置使其居中
model.position.x -= center.x;
model.position.y -= center.y;
model.position.z -= center.z;
}
// 使用示例
loader.load('model.gltf', (gltf) => {
const model = gltf.scene;
scene.add(model);
centerModel(model);
});
方法二:使用 geometry.center() 居中几何体
loader.load('model.gltf', (gltf) => {
const model = gltf.scene;
// 遍历所有子网格并居中几何体
model.traverse((child) => {
if (child.isMesh) {
child.geometry.center();
}
});
scene.add(model);
});
方法三:使用 Group 容器调整层级
loader.load('model.gltf', (gltf) => {
const model = gltf.scene;
const group = new THREE.Group();
// 计算模型中心
const box = new THREE.Box3().setFromObject(model);
const center = box.getCenter(new THREE.Vector3());
// 调整模型位置使其在 Group 中居中
model.position.copy(center.negate());
group.add(model);
scene.add(group);
// 后续对 group 进行旋转/缩放操作将保持模型居中
});
四、完整示例代码
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 场景初始化
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 相机设置
camera.position.set(0, 0, 5);
// 添加轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
// 添加光源
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 5, 5);
scene.add(directionalLight);
// 模型加载与居中
const loader = new GLTFLoader();
loader.load(
'path/to/your/model.gltf',
(gltf) => {
const model = gltf.scene;
// 模型居中处理
model.updateMatrixWorld();
const box = new THREE.Box3().setFromObject(model);
const center = box.getCenter(new THREE.Vector3());
model.position.x -= center.x;
model.position.y -= center.y;
model.position.z -= center.z;
scene.add(model);
// 自动调整相机位置
const size = box.getSize(new THREE.Vector3());
const maxDim = Math.max(size.x, size.y, size.z);
const fov = camera.fov * (Math.PI / 180);
const distance = maxDim / 2 / Math.tan(fov / 2);
camera.position.set(0, 0, distance * 1.5);
camera.lookAt(0, 0, 0);
}
);
// 渲染循环
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
// 窗口大小调整
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
五、常见问题与解决方案
1. 模型加载后看不到
- 检查模型路径是否正确
- 确保场景中有光源(PBR 材质需要光照才能显示)
- 尝试调整相机位置或缩放模型
2. 模型显示异常
- 检查模型格式是否正确(推荐使用 .glb 格式)
- 确保 Three.js 版本与模型导出工具兼容
- 尝试更新 Three.js 到最新版本
3. 居中后模型位置异常
- 确保在调用 centerModel 前模型已完全加载
- 检查模型是否有父级对象影响其位置
- 尝试重新计算包围盒