Three.js 是什么——网页里的 3D 世界从这里开始(一)
1. 定位导航学习 Three.js不要一上来就背 API。很多初学者第一次看到 Three.js最容易被这些对象绕晕constscenenewTHREE.Scene();constcameranewTHREE.PerspectiveCamera();constrenderernewTHREE.WebGLRenderer();constgeometrynewTHREE.BoxGeometry();constmaterialnewTHREE.MeshBasicMaterial();constcubenewTHREE.Mesh(geometry,material);这些代码并不长但如果不知道每个对象的职责后面学习模型加载、灯光、材质、动画、控制器、后处理时会越来越乱。本篇只解决一个问题Three.js 是什么先给一个小白友好的理解Three.js 是浏览器里的 3D 开发工具箱。它不是建模软件不负责像 Blender 那样“捏模型”它也不是单纯的动画库不只是让对象动起来。它的核心价值是把复杂的 WebGL / WebGPU 渲染过程封装成更容易理解和组合的对象例如Scene、Camera、Renderer、Mesh、Geometry、Material、Light、Texture。如果把网页 3D 看成拍电影Three.js 对象类比Scene拍摄现场 / 舞台Camera摄影机Renderer摄影机输出到屏幕的设备Mesh镜头里能看到的演员或道具Geometry道具的形状骨架Material道具表面的材质、颜色、质感Light灯光师打的灯Texture贴在物体表面的图片纹理理解这张“剧组分工表”比一开始死背 API 更重要。2. Three.js 的一句话定义Three.js 是一个 JavaScript 3D 图形库。它可以让我们在浏览器中创建丰富的 3D 内容。更准确地说Three.js 是运行在浏览器中的 3D 渲染库。它在 WebGL / WebGPU 之上封装了场景管理、相机、几何体、材质、灯光、纹理、模型加载、动画、交互和后处理等能力。这句话里有三个关键词。第一运行在浏览器中。这意味着用户不需要安装客户端只要打开网页就可以看到 3D 内容。第二3D 渲染库。它主要解决的是“怎么把 3D 世界画出来”的问题包括物体怎么显示、光怎么照、相机怎么看、画面怎么更新。第三封装 WebGL / WebGPU。WebGL / WebGPU 更接近底层图形接口能力强但使用复杂Three.js 在上层提供了更容易使用的对象和工具。所以Three.js 更像是网页 3D 世界的搭建工具。你把模型、灯光、材质、相机和动画交给它它负责把这些内容组织起来并渲染到浏览器画布上。3. Three.js 和 WebGL / WebGPU 的关系WebGL 很强但它非常底层。如果直接写 WebGL你要自己处理很多底层细节。对于初学者来说直接从 WebGL 开始写 3D就像还没学会开车先被要求从发动机、变速箱、轮胎和传动轴开始组装一辆车。你当然可以这么做但学习曲线会非常陡。Three.js 的价值就是把这些底层细节封装成更容易理解的对象。层级名称小白理解页面显示层Canvas3D 画面最终显示的地方底层图形接口WebGL浏览器里的底层 3D 绘图接口新一代图形接口WebGPU更现代、更强的 GPU 图形与计算接口上层开发库Three.js帮我们更方便地写 3D 场景可以这样理解技术类比WebGL发动机、零件、底层机械结构WebGPU更现代的新一代发动机和计算平台Three.js已经组装好的汽车业务代码你开车去哪里、拉什么货、走什么路线Three.js 并没有让底层复杂度消失而是把它们隐藏在更适合业务开发的对象后面。你仍然可以深入到底层但一开始不必被底层细节困住。4. Three.js 在浏览器 3D 技术栈中的位置这张图表达的是业务代码 → Three.js → WebGL / WebGPU → Canvas → 屏幕显示你的业务代码可能是在做产品展示、数字孪生、3D 地图、3D 图表或 WebXR 展厅。Three.js 在中间负责把业务对象转换成 3D 场景对象例如模型、灯光、相机、材质、纹理、动画。WebGL / WebGPU 在更底层负责和浏览器图形能力、GPU 渲染能力打交道。Canvas 是最终承载画面的地方用户看到的所有 3D 内容最终都会显示在页面中的画布上。5. 一个 Three.js 程序由什么组成一个基础 Three.js 应用通常会创建很多对象并把它们关联起来Renderer接收Scene和CameraScene负责存放 3D 对象Camera决定从哪个角度观察Mesh是真正可见的 3D 物体Geometry决定形状Material决定表面显示Light决定光照效果Texture可以把图片贴到物体表面这些内容直接用文字列很容易枯燥所以放在下面这张图里。5.1 核心对象表对象中文名作用小白类比Renderer渲染器把 3D 场景画到 Canvas 上画家Scene场景存放所有 3D 对象舞台Camera相机决定从哪里看场景眼睛Mesh网格一个可见的 3D 物体舞台上的演员Geometry几何体决定物体形状骨架Material材质决定物体表面皮肤 / 衣服Light灯光让物体有明暗灯Texture纹理图片贴到物体表面贴纸这张表非常重要。后面你看到任何复杂的 Three.js 项目都可以先问自己这个项目的Scene是什么主Camera在哪里Renderer把内容画到哪个canvas哪些对象是Mesh每个Mesh的Geometry和Material分别是什么有没有灯光有没有纹理有没有动画能回答这些问题Three.js 的入门主线就清楚了。6. Three.js 基础程序结构Renderer 需要 Scene Camera。Scene 里面放 Mesh 和 Light。Mesh 由 Geometry 和 Material 组合而成。用一句代码表达核心渲染动作就是renderer.render(scene,camera);这行代码的意思是请渲染器使用这个相机的视角把这个场景画出来。看似简单的一行背后其实串起了整个 Three.js 基础结构。7. Mesh Geometry Material学习 Three.js最先要记住这个公式MeshGeometryMaterial\text{Mesh} \text{Geometry} \text{Material}MeshGeometryMaterial换成中文就是网格对象 几何体 材质部分决定什么例子Geometry形状立方体、球体、平面、圆柱Material表面颜色、金属感、粗糙度、透明度Mesh可见物体一个真正放进场景的 3D 对象创建一个绿色立方体constgeometrynewTHREE.BoxGeometry(1,1,1);constmaterialnewTHREE.MeshBasicMaterial({color:0x44aa88});constcubenewTHREE.Mesh(geometry,material);含义是代码含义BoxGeometry(1, 1, 1)创建一个 1 × 1 × 1 的立方体形状MeshBasicMaterial({ color: 0x44aa88 })创建一个绿色表面new THREE.Mesh(geometry, material)把形状和表面组合成一个可见物体很多初学者会把Geometry、Material、Mesh混在一起。其实你只要记住没有Geometry物体没有形状没有Material物体不知道该怎么显示没有Mesh形状和材质还没有组合成可放进场景的对象8. 第一个立方体旋转过程这张动态图展示的是一个 Three.js 入门程序的运行过程创建项目安装 Three.js创建 Canvas创建 Renderer创建 Scene创建 Camera创建 Mesh添加 Light启动动画循环每一帧更新旋转并重新渲染真正的关键不在于“立方体会转”而在于你要理解动画不是自动发生的。我们每一帧都在修改物体的rotation然后调用renderer.render(scene, camera)重新绘制。9. Three.js 小白学习路线入门阶段最容易犯的错误是一开始就追求炫酷效果比如水面、粒子、Shader、WebGPU、后处理。那些内容当然重要但不是第一步。更稳妥的路线是先理解 Scene、Camera、Renderer再理解 Mesh、Geometry、Material然后写出第一个立方体接着让它旋转、加灯光、加控制器、加载模型。只要这个主线跑通后面再去学材质、纹理、动画、模型、后处理就不会散。10. 常见误区误区一Three.js 是建模软件不是。Three.js 不等于 Blender、Maya、3ds Max。它不是用来“建模”的软件而是用来在网页里加载、组织、渲染和交互展示 3D 内容的库。实际项目里常见流程是环节工具建模Blender / Maya / 3ds Max / CAD模型导出glTF / GLB / OBJ / STL网页加载与展示Three.js交互与业务系统JavaScript / TypeScript / 前端框架误区二Three.js 和 WebGL 是一回事不是。WebGL 是底层图形接口。Three.js 是基于 WebGL / WebGPU 的上层封装。误区三Three.js 只适合做炫酷网页不对。Three.js 不仅能做炫酷网页也非常适合做工程系统。例如场景说明数字孪生用 3D 场景展示真实世界的设备、建筑、流程和状态3D 机房展示机柜、服务器、温湿度、告警、链路状态智慧园区展示楼宇、道路、人员、车辆、安防事件工业模型查看器加载 STL、OBJ、glTF、3MF 等模型点云可视化展示激光雷达、扫描数据、空间点集WebXR 展厅通过 VR / AR 展示产品和空间所以Three.js 不是玩具库。它既能做视觉创意也能做严肃工程系统。11. 创建流程使用 Vite 搭建 Three.js 项目后续所有有代码的章节都先给出 Vite 创建流程。11.1 JavaScript 项目创建流程npmcreate vitelatest threejs-001-js ----templatevanillacdthreejs-001-jsnpminstallnpminstallthreenpmrun dev核心目录threejs-001-js ├── index.html ├── package.json └── src ├── main.js └── style.css11.2 TypeScript 项目创建流程npmcreate vitelatest threejs-001-ts ----templatevanilla-tscdthreejs-001-tsnpminstallnpminstallthreenpmrun dev核心目录threejs-001-ts ├── index.html ├── package.json ├── tsconfig.json └── src ├── main.ts └── style.css11.3 Vue3 项目创建流程npmcreate vitelatest threejs-001-vue3 ----templatevue-tscdthreejs-001-vue3npminstallnpminstallthreenpmrun dev核心目录threejs-001-vue3 ├── index.html ├── package.json └── src ├── main.ts ├── App.vue └── style.css11.4 React 项目创建流程npmcreate vitelatest threejs-001-react ----templatereact-tscdthreejs-001-reactnpminstallnpminstallthreenpmrun dev核心目录threejs-001-react ├── index.html ├── package.json └── src ├── main.tsx ├── App.tsx └── style.css11.5 Angular 项目创建流程Angular 项目没有官方 Vite 模板本节使用 Angular CLI 创建。npminstall-gangular/cli ng new threejs-001-angular--stylecss--routingfalsecdthreejs-001-angularnpminstallthreenpmstart核心目录threejs-001-angular └── src ├── main.ts ├── styles.css └── app ├── app.component.ts ├── app.component.html └── app.component.css12. 代码实践本章提供 5 套代码版本路径JavaScriptcode/threejs-001-js/TypeScriptcode/threejs-001-ts/Vue3code/threejs-001-vue3/Reactcode/threejs-001-react/Angularcode/threejs-001-angular/每套代码都实现同一个目标创建场景、创建相机、创建渲染器、创建三个立方体、添加灯光、让立方体旋转并在窗口变化时自动适配。12.1 JavaScript 版本完整代码见code/threejs-001-js/入口文件code/threejs-001-js/src/main.js12.2 TypeScript 版本完整代码见code/threejs-001-ts/入口文件code/threejs-001-ts/src/main.ts12.3 Vue3 版本完整代码见code/threejs-001-vue3/入口组件code/threejs-001-vue3/src/App.vue12.4 React 版本完整代码见code/threejs-001-react/入口组件code/threejs-001-react/src/App.tsx12.5 Angular 版本完整代码见code/threejs-001-angular/入口组件code/threejs-001-angular/src/app/app.component.ts13. API 速查API类型作用THREE.WebGLRenderer渲染器把 3D 场景画到 canvasTHREE.Scene场景存放 3D 对象THREE.PerspectiveCamera相机创建透视视角THREE.BoxGeometry几何体创建立方体形状THREE.MeshPhongMaterial材质创建受光照影响的材质THREE.Mesh网格几何体 材质THREE.DirectionalLight灯光创建平行光THREE.AmbientLight灯光创建环境光renderer.render(scene, camera)方法渲染场景requestAnimationFrame浏览器 API创建动画循环14. 常见问题排查问题可能原因解决方式页面黑屏相机位置不对调整camera.position.z页面黑屏没有执行renderer.render检查动画循环物体看不见没有scene.add(mesh)把 Mesh 加入场景物体很黑材质需要灯光但没有灯添加DirectionalLight画面变形窗口变化后没更新相机调用camera.updateProjectionMatrix()控制台报 import 错误没有使用模块方式使用script typemodulecanvas 有滚动条body 默认 marginCSS 设置margin: 0Vue / React 页面重复渲染异常没有清理动画和资源卸载时cancelAnimationFrame和disposeAngular 中this丢失resize / animate 方法绑定问题使用箭头函数15. 本章小结用一句话收尾Three.js 不是神秘的黑盒它只是把浏览器 3D 开发中的复杂底层过程封装成了一组更容易理解和组合的对象。先理解 Scene、Camera、Renderer、Mesh、Geometry、Material、Light后面的模型加载、动画、交互和数字孪生都会清晰很多。16. 作业作业 1修改颜色把三个立方体颜色改成红色、黄色、蓝色。createCube(0xff0000,-2);createCube(0xffff00,0);createCube(0x0000ff,2);作业 2增加数量把 3 个立方体改成 5 个立方体。要求说明颜色每个立方体颜色不同位置每个立方体位置不同旋转每个立方体旋转速度不同作业 3修改相机尝试修改camera.position.z3;camera.position.z8;camera.position.y2;观察画面有什么变化。作业 4修改材质把newTHREE.MeshPhongMaterial()改成newTHREE.MeshBasicMaterial()观察灯光是否还会影响立方体。作业 5框架改造任选 Vue3、React、Angular 中的一个版本完成以下任务任务要求添加物体添加第 4 个立方体修改背景修改场景背景色修改动画修改旋转速度释放资源组件卸载时清理动画和 Three.js 资源17. 思考题为什么 Three.js 需要Scene、Camera、Renderer三个核心对象少一个会怎样为什么Mesh不是单独存在的而是由Geometry和Material组合出来的为什么相机默认在原点时可能看不到放在原点的立方体为什么MeshPhongMaterial需要灯光而MeshBasicMaterial不需要灯光如果要做一个 3D 机房系统哪些对象属于Mesh哪些对象属于Light哪些对象属于CameraVue3、React、Angular 中接入 Three.js 时为什么都要在组件卸载时清理动画和资源