概览
写在前面
在高级前端或图形开发面试中,仅仅会调用 Three.js 的 API 拼凑一个场景是远远不够的。面试官更看重你对 WebGL 渲染流水线、矩阵变换、场景图(Scene Graph)、性能瓶颈与优化方案 的深度理解。
Three.js 本质上是对原生 WebGL 的高度面向对象封装,它屏蔽了复杂的着色器(Shader)编写、上下文管理和底层 Buffer 数据绑定,提供了一套更符合人类直觉的 3D 编程模型。
注意:Three.js 默认使用右手坐标系(x轴向右,y轴向上,z轴向屏幕外),这与 OpenGL/WebGL 的默认坐标系一致。
核心架构:场景图与渲染流
1. 场景图 (Scene Graph) 与 矩阵变换
这是 Three.js 中最重要的架构概念。整个 3D 场景在底层是一个有向无环图 (DAG),我们称之为场景图。
- 场景图中的每一个节点都是一个
Object3D实例(Mesh, Camera, Light, Group 都继承自它)。 - 局部矩阵与世界矩阵:每个对象都有一个局部变换矩阵(记录相对于父节点的平移、旋转、缩放)。当渲染器进行渲染时,它会从 Scene 根节点开始递归遍历整棵树,把局部矩阵与父节点的世界矩阵相乘,计算出当前对象的世界矩阵(World Matrix),最终决定它在 3D 空间中的绝对位置。
2. 相机 (Camera) 与 视锥体
决定场景中哪些角度的内容会显示出来。最常用的是基于透视投影的 PerspectiveCamera,它会模拟人眼的视觉效果(近大远小)。
🎯 面试考点:视锥体裁剪 (Frustum Culling) 透视相机的四个参数(fov, aspect, near, far)定义了一个截头锥体(Frustum)。在每一帧渲染前,Three.js 会计算物体的包围盒(Bounding Box/Sphere),如果包围盒完全在这个椎体之外,该物体就不会被提交给 GPU 渲染。这是 Three.js 默认开启的核心性能优化手段。
3. 渲染器 (Renderer) 底层工作流
执行 renderer.render(scene, camera) 时,底层发生了什么?
- 更新矩阵:递归遍历 Scene Graph,更新所有有变动对象的世界矩阵。
- 收集与分类:收集所有的光源、网格对象(Mesh)。
- 视椎体裁剪:丢弃不在相机视野内的 Mesh。
- 排序 (Sorting):将不透明对象(从前向后渲染,利用 GPU 深度测试 Early-Z 剔除被遮挡像素)和透明对象(从后向前渲染,利用 Alpha Blending 正确混合颜色)分别排序。
- Draw Call 提交:将数据绑定到 WebGL 的 Buffer 中,挂载 Shader,向 GPU 发出 Draw Call 绘制指令。
场景基石:物体组成要素
在 WebGL 层,只有点、线、三角形。Three.js 通过以下概念将其抽象:
几何体 (Geometry / BufferGeometry)
定义了物体的形状和顶点数据。
- 面试注意点:现代 Three.js 已经废弃了低效的
Geometry,全面拥抱BufferGeometry。它的底层直接对应 WebGL 的BufferAttribute(如 position, normal, uv),数据以一维强类型数组(TypedArray)的形式存储在内存中,极大提升了向 GPU 传输数据的效率。
材质 (Material) 与 纹理 (Texture)
- 材质:定义了几何体表面的光学属性(如何对光照产生反应)。比如不受光照影响的
MeshBasicMaterial,以及基于物理渲染的MeshStandardMaterial(PBR)。 - 纹理:包裹到几何体表面的图像数据。一张 PBR 材质通常需要组合多张纹理(如颜色贴图、法线贴图、粗糙度贴图)。
网格 (Mesh)
Mesh = Geometry + Material。它是 3D 场景中最常见的可见对象。除了 Mesh,还有 Points(粒子点云)、Line(线段)等基类。
交互与动画
1. 动画驱动 (RequestAnimationFrame)
3D 场景的动画本质上是不断改变物体的属性并重新调用 render。必须使用 requestAnimationFrame 而不是 setInterval,以保证屏幕刷新率同步并避免后台标签页的无效渲染。复杂骨骼动画通常由 AnimationMixer 驱动。
2. 射线拾取 (Raycaster)
🎯 面试高频题:如何在 3D 场景中实现鼠标点击物体的交互? 因为屏幕是 2D 的,场景是 3D 的,直接绑定 click 事件是无效的。需要使用光线投射技术 (Raycasting):
- 将鼠标在屏幕上的 2D 坐标归一化(映射到 -1 到 1 的标准化设备坐标 NDC)。
- 基于相机的位置和方向,从鼠标位置向 3D 空间发射一条射线。
- 计算射线与场景中物体包围盒/三角面的相交情况,按距离排序返回结果。
进阶:性能优化
3D 应用的性能瓶颈通常在于 Draw Call 过多和显存溢出。关于如何进行几何体合并、实例化渲染、纹理模型压缩以及内存泄漏管理等大厂必考的优化方案,详见 性能优化。
知识延伸导航
- 原生 WebGL 基础:渲染管线、Hello Triangle、缓冲区绑定、WebGL vs WebGPU
- 坐标变换与矩阵:MVP 矩阵推导、坐标空间转换、四元数(Quaternion)避免万向节死锁
- 着色器 (Shader):GLSL 语法、ShaderMaterial 自定义材质实战
- 光照与材质:PBR 物理渲染、实时阴影(Shadow Mapping)的实现机制
- Web3D 进阶应用:后期处理(Post-processing)、粒子系统点云实战