Three.js 学习路线图
Three.js 是一个强大的 3D JavaScript 库,但它的学习曲线相对陡峭,一个清晰的学习路径至关重要。
基础准备与环境搭建
在开始之前,你需要具备一些基础知识:
- HTML/CSS: 网页开发的基础。
- JavaScript (ES6+): 这是最重要的前提,你需要熟练掌握变量、函数、对象、数组、
Promise、async/await以及 ES6 的模块化 (import/export)。 - 开发工具: 一个好的代码编辑器,如 VS Code,以及一个本地服务器(因为 Three.js 应用需要通过 HTTP 协议运行,不能直接用
file://打开),VS Code 的 Live Server 插件可以轻松实现这一点。
环境搭建步骤:
- 创建一个项目文件夹,
my-threejs-project。 - 在文件夹中创建三个文件:
index.html,style.css,main.js。 - 在
index.html中引入你的 JavaScript 文件。 - 使用 Live Server 运行
index.html。
核心概念详解 (Three.js 的“Hello World”)
这是 Three.js 的最小化工作流程,理解了这五部分,你就掌握了核心。
场景
- 作用: 一个容器,用来放置所有你的 3D 对象(物体、光源、相机等)。
- 类比: 一个虚拟的舞台,你将在上面表演。
import * as THREE from 'three'; const scene = new THREE.Scene(); scene.background = new THREE.Color(0x00ff00); // 设置场景背景为绿色
相机
- 作用: 定义你如何观察场景,它决定了场景的哪一部分会被渲染到屏幕上。
- 常用相机:
PerspectiveCamera(透视相机,模拟人眼,有近大远小的效果)。 - 参数:
fov (Field of View): 视野角度,值越大,看到的范围越广。aspect: 宽高比,通常是画布的宽度除以高度。near: 近裁剪面,比这个近的物体将不会被渲染。far: 远裁剪面,比这个远的物体也不会被渲染。
const camera = new THREE.PerspectiveCamera( 75, // fov window.innerWidth / window.innerHeight, // aspect 0.1, // near 1000 // far ); camera.position.z = 5; // 将相机沿 Z 轴向后移动 5 个单位
渲染器
- 作用: 负责将场景和相机组合起来,并将最终结果绘制到网页的
<canvas>元素上。 - 参数:
WebGLRenderer是最常用的,它利用 GPU 进行加速。
const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); // 设置渲染器大小为窗口大小 document.body.appendChild(renderer.domElement); // 将渲染器的 canvas 添加到页面中
物体
- 作用: 场景中的具体对象,如立方体、球体、模型等。
- 构成:
- 几何体: 物体的形状,如
BoxGeometry(立方体),SphereGeometry(球体),ConeGeometry(圆锥体)。 - 材质: 物体的外观,如颜色、光泽、透明度等,如
MeshBasicMaterial(不受光照影响的基础材质),MeshStandardMaterial(受光照影响的 PBR 材质,更真实)。 - 网格: 将几何体和材质组合在一起的对象。
- 几何体: 物体的形状,如
// 创建几何体
const geometry = new THREE.BoxGeometry();
// 创建材质
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// 创建网格
const cube = new THREE.Mesh(geometry, material);
scene.add(cube); // 将立方体添加到场景中
动画循环
- 作用: 让场景“活”起来,每一帧都重新渲染场景,从而产生动画效果。
- 关键: 使用
requestAnimationFrame,它会在浏览器下一次重绘之前调用指定的回调函数,实现高效流畅的动画。
function animate() {
requestAnimationFrame(animate); // 循环调用 animate
// 让立方体旋转
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera); // 渲染场景
}
animate(); // 启动动画循环
完整 main.js 示例:
import * as THREE from 'three';
// 1. 场景
const scene = new THREE.Scene();
// 2. 相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
// 3. 渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 4. 物体
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// 5. 动画循环
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
深入探索与实践
掌握了基础后,你需要学习更多让 3D 世界变得生动有趣的知识。
光照
没有光照,MeshBasicMaterial 之外的材质看起来都是黑色的。
- 环境光: 模拟环境中的漫反射光,均匀照亮所有物体,没有方向。
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);
材质进阶
MeshStandardMaterial: 目前最常用、最真实的材质,它需要光源才能显示,并支持 PBR (Physically Based Rendering,基于物理的渲染)。const material = new THREE.MeshStandardMaterial({ color: 0x00ff00, metalness: 0.5, // 金属感 roughness: 0.2 // 粗糙度 });- 纹理: 将图片作为材质的表面细节。
const textureLoader = new THREE.TextureLoader(); const texture = textureLoader.load('path/to/your/texture.jpg'); const material = new THREE.MeshStandardMaterial({ map: texture });
加载 3D 模型 通常不会手动创建所有复杂的几何体,而是从外部加载。
- 常用格式:
GLTF(推荐),OBJ,FBX。 - 工具:
GLTFLoader是 Three.js 内置的加载器。 - 流程:
- 使用建模软件 (如 Blender, Maya) 导出模型为
.gltf或.glb格式。 - 使用
GLTFLoader加载模型文件。 - 将加载的模型添加到场景中。
- 使用建模软件 (如 Blender, Maya) 导出模型为
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; // 注意路径
const loader = new GLTFLoader();
loader.load(
'models/your_model.gltf', // 模型路径
function (gltf) {
scene.add(gltf.scene); // 将模型的所有部分添加到场景
console.log('模型加载成功');
},
function (xhr) {
console.log((xhr.loaded / xhr.total * 100) + '% loaded'); // 加载进度
},
function (error) {
console.error('模型加载失败', error);
}
);
交互 让用户能够与 3D 场景进行交互。
-
OrbitControls: 最常用的控制器,允许用户通过鼠标拖拽来旋转、缩放和平移视角。import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; const controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; // 启用阻尼(惯性),使控制感觉更平滑 controls.dampingFactor = 0.05;在动画循环中需要更新控制器:
function animate() { requestAnimationFrame(animate); controls.update(); // 更新控制器 renderer.render(scene, camera); }
响应式设计 确保你的 3D 场景能适应窗口大小的变化。
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix(); // 更新相机投影矩阵
renderer.setSize(window.innerWidth, window.innerHeight);
}
项目实战与资源推荐
入门级项目
- 旋转的地球: 使用球体几何体、地球纹理和
OrbitControls。 - 简单汽车模型: 加载一个简单的汽车 GLTF 模型,并让它沿路径移动。
- 粒子系统: 使用
Points和PointsMaterial创建星空或火焰效果。
进阶级项目
- 3D 产品展示: 创建一个交互式的产品查看器,用户可以旋转、缩放产品,并更换颜色/材质。
- 建筑漫游: 加载一个建筑模型,实现第一人称或鸟瞰视角的漫游。
- 小游戏: 开发一个简单的 3D 游戏,如滚动的球体躲避障碍物。
推荐资源
-
官方文档:
- Three.js 官方文档: 最权威的参考,但可能对新手不够友好。
- Three.js 示例: 大量可运行的代码示例,是学习新功能的最佳途径。
-
优质教程:
- Brackeys (YouTube): 虽然已停止更新,但他的 Three.js 系列教程是经典中的经典,非常适合入门。
- The Cherno (YouTube): 他的 "Creating a 3D Engine" 系列视频深入浅出,不仅教你 Three.js,还教你 3D 图形学的基础原理。
- Bruno Simon (threejs-journey.com): 强烈推荐! 这是一份付费的、结构化极好的在线课程,内容全面且紧跟最新版本,是系统学习的最佳选择。
- GeeksforGeeks: 有一些不错的 Three.js 教程文章。
-
社区与工具:
- Discord: Three.js 的官方 Discord 频道,可以提问和交流。
- CodeSandbox / StackBlitz: 在线代码编辑器,非常适合快速创建和分享 Three.js 项目。
- Blender: 免费、开源的 3D 建模软件,用于创建和导出 3D 模型。
学习建议
- 动手敲代码: 不要只看教程,一定要自己动手实现每一个例子。
- 从模仿开始: 找一个你喜欢的 Three.js 作品,尝试去模仿它,在模仿中学习。
- 分解问题: 遇到复杂的功能时,把它分解成小步骤(先加载模型,再让它动起来,最后添加交互)。
- 学会调试: 学会使用浏览器的开发者工具来检查你的代码、查看错误信息。
- 保持耐心: 3D 开发有难度,遇到挫折是正常的,坚持下去,你会看到自己的进步。
祝你学习愉快!
