系列文章目录
Three.js 快速入门教程【一】开启你的 3D Web 开发之旅
Three.js 快速入门教程【二】透视投影相机
Three.js 快速入门教程【三】渲染器
Three.js 快速入门教程【四】三维坐标系
Three.js 快速入门教程【五】动画渲染循环
Three.js 快速入门教程【六】相机控件 OrbitControls
Three.js 快速入门教程【七】常见几何体类型
Three.js 快速入门教程【八】常见材质类型
Three.js 快速入门教程【九】光源类型
Three.js 快速入门教程【十】常见的纹理类型
Three.js 快速入门教程【十一】天空盒的多种实现方式
Three.js 快速入门教程【十二】外部模型加载
Three.js 快速入门教程【十三】外部模型加载后常见的处理操作
Three.js 快速入门教程【十四】使用Stats.js监控渲染帧率和性能优化
Three.js 快速入门教程【十五】交互神器DragControls使用详解,实现对物体或模型拖拽
Three.js 快速入门教程【十六】调试神器 gui.js使用详解,可视化面板控制场景参数提高开发效率
文章目录
一、前言
在使用 Three.js 进行 3D 场景开发时,加载外部模型是一项非常常见且重要的操作。通过加载外部模型,我们可以快速丰富场景内容,实现更加复杂和逼真的 3D 效果。本教程将详细介绍如何在 Three.js 中加载常见的 3D 模型格式。
二、常见的模型格式
Three.js支持多种3D模型格式,推荐使用以下格式:
-
GlTF(.glb/.gltf):专为Web设计的开放格式(推荐首选)
-
FBX:Autodesk通用格式
-
OBJ+MTL:简单几何体格式
二、基础加载流程
以glb格式为例,先了解下加载流程核心代码
//导入gltf加载器
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.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 });
// 创建加载器实例
const loader = new GLTFLoader();
// 异步加载模型
loader.load(
'models/demo.glb',//模型路径,脚手架项目可放置public目录
(gltf) => {
const model = gltf.scene;
// 调整模型参数
model.position.set(0, -1, 0);
model.scale.set(0.5, 0.5, 0.5);
scene.add(model);
},
(xhr) => {
console.log(`已加载 ${(xhr.loaded / xhr.total * 100)}%`);
},
(error) => {
console.error('加载失败:', error);
}
);
从上述代码可以看出,模型加载需要通过特定的加载器进行加载解析,如gltf格式的模型需要GLTFLoader加载器,加载成功获取到模型对象调整位置、大小等属性添加到场景中即可。
(1)加载器选择
根据模型格式选择对应的加载器:
-
GLTFLoader:处理glTF/glb格式(Web首选格式)
-
FBXLoader:加载Autodesk FBX文件
-
OBJLoader+MTLLoader:配合处理带材质的OBJ模型
(2)异步加载过程
通过loader.load()方法实现异步加载,该方法接收三个核心回调函数:
-
模型文件URL:建议使用相对路径(例如assets/models/character.glb)
-
加载完成回调:接收解析后的模型数据(gltf.scene为根对象)
-
进度监控回调:通过xhr对象获取加载百分比
-
错误处理回调:捕获网络请求或文件解析异常
(3)模型调整
获取模型后通常需要基础适配操作,可根据实际需要操作:
model.position.set(0, 0, 0); // 设置初始位置
model.scale.set(0.5, 0.5, 0.5); // 缩放至合适尺寸
model.rotation.y = Math.PI/2; // 绕Y轴旋转90度
scene.add(model); // 将模型加入场景
三、完整示例代码
1、GlTF(.glb/.gltf)格式
import * as THREE from "three";
//引入相机控制器
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
// 创建场景
const scene = new THREE.Scene();
//坐标辅助线
const axesHelper = new THREE.AxesHelper(500);
scene.add(axesHelper);
// 创建相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
3000
);
camera.position.set(0,5,10)
// 添加环境光
const ambientLight = new THREE.AmbientLight(0xffffff, 1);
scene.add(ambientLight);
//添加平行光
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(-5, 2, 20);
scene.add(light);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建加载器实例
const loader = new GLTFLoader();
// 异步加载模型
loader.load(
"models/pz.gltf",
(gltf) => {
const model = gltf.scene;
// 调整模型参数
model.position.set(0, 0, 0);
//相机看向模型
camera.lookAt(model);
scene.add(model);
},
(xhr) => {
console.log(`已加载 ${(xhr.loaded / xhr.total) * 100}%`);
},
(error) => {
console.error("加载失败:", error);
}
);
// 创建 OrbitControls 控件
const controls = new OrbitControls(camera, renderer.domElement);
// 渲染循环
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
运行效果:
2、FBX格式
import * as THREE from "three";
//引入相机控制器
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader";
// 创建场景
const scene = new THREE.Scene();
//坐标辅助线
const axesHelper = new THREE.AxesHelper(500);
scene.add(axesHelper);
// 创建相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
3000
);
camera.position.set(0, 5, 10);
// 添加环境光
const ambientLight = new THREE.AmbientLight(0xffffff, 1);
scene.add(ambientLight);
//添加平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 5);
directionalLight.position.set(-5, 2, 20);
scene.add(directionalLight);
const directionalLight2 = new THREE.DirectionalLight(0xffffff, 5);
directionalLight.position.set(5, -2, -20);
scene.add(directionalLight2);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建加载器
const fbxLoader = new FBXLoader();
// 异步加载模型
fbxLoader.load(
"su7/Xiaomi_SU7.FBX",
(fbx) => {
const model = fbx;
// 调整模型参数
model.position.set(0, 0, 0);
model.scale.set(0.01, 0.01, 0.01);
//相机看向模型
camera.lookAt(model);
scene.add(model);
},
(xhr) => {
console.log(`已加载 ${(xhr.loaded / xhr.total) * 100}%`);
},
(error) => {
console.error("加载失败:", error);
}
);
// 创建 OrbitControls 控件
const controls = new OrbitControls(camera, renderer.domElement);
// 渲染循环
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
运行效果:
3、OBJ+MTL格式
import * as THREE from "three";
//引入相机控制器
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader.js";
import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader";
// 创建场景
const scene = new THREE.Scene();
//坐标辅助线
const axesHelper = new THREE.AxesHelper(500);
scene.add(axesHelper);
// 创建相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
3000
);
camera.position.set(0, 5, 10);
// 添加环境光
const ambientLight = new THREE.AmbientLight(0xffffff, 1);
scene.add(ambientLight);
//添加平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 5);
directionalLight.position.set(-5, 2, 20);
scene.add(directionalLight);
const directionalLight2 = new THREE.DirectionalLight(0xffffff, 5);
directionalLight.position.set(5, -2, -20);
scene.add(directionalLight2);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建OBJ加载器
const objLoader = new OBJLoader();
const mtlLoader = new MTLLoader();
mtlLoader.load("obj/ld.mtl", (materials) => {
materials.preload();
// 异步加载模型
objLoader.setMaterials(materials).load(
"obj/ld.obj",
(obj) => {
const model = obj;
// 调整模型参数
model.position.set(0, 0, 0);
model.scale.set(0.5, 0.5, 0.5);
//相机看向模型
camera.lookAt(model);
scene.add(model);
},
(xhr) => {
console.log(`已加载 ${(xhr.loaded / xhr.total) * 100}%`);
},
(error) => {
console.error("加载失败:", error);
}
);
});
// 创建 OrbitControls 控件
const controls = new OrbitControls(camera, renderer.domElement);
// 渲染循环
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
运行效果:
四、免费模型资源下载
免费的模型资源下载测试可以访问Poly Haven网站,该网站不仅有免费纹理资源还有3d模型和全景图片提供下载调试
五、总结
通过本篇教程,我们了解了加载外部模型的基本流程以及学会不同格式模型文件的加载方法。模型加载是3D可视化开发的基础技能,但也仅仅是起点,还有诸如模型动画、物理效果和着色器改造更多开发技能等着你学习,在实践中掌握技巧,让你的3D场景更具生命力。
更多three.js入门知识点请关注该系列教程后续的更新。