不能直接用new WebGLRenderingContext()写3D,因其需手写着色器、绑定缓冲区、管理VAO、实现矩阵变换与投影,最简立方体代码常超300行且易因gl.useProgram时机错误等导致静默失败。

Three.js 不是“可选工具”,而是当前 Web 端 3D 开发的事实标准——跳过它直接写原生 WebGL,等于手动重写渲染管线、矩阵变换、着色器编译和资源管理,90% 的项目会卡在 gl.getUniformLocation 返回 null 或黑屏无报错上。
为什么不能直接用 new WebGLRenderingContext() 写 3D?
原生 WebGL 需要你手写顶点/片元着色器、绑定缓冲区、设置 attribute 和 uniform、管理 VAO、处理矩阵堆栈、自行实现相机投影与视图变换。一个最简立方体渲染,代码量常超 300 行,且极易因 gl.useProgram 时机错误或 gl.enableVertexAttribArray 漏调导致静默失败。Three.js 把这些封装进 THREE.Scene、THREE.Mesh、THREE.Camera 等对象,让开发者聚焦于“加什么物体”“放哪儿”“怎么动”,而非“GPU 怎么读内存”。
THREE.WebGLRenderer 初始化时必须注意的三件事
常见黑屏/白屏/报错大多源于这三项配置不匹配:
-
canvas元素必须已挂载到 DOM 中,且尺寸不为 0;用document.body.appendChild(renderer.domElement)最稳妥,别依赖未插入的document.createElement('canvas') - 渲染器默认不自动调整尺寸,需监听
window.resize并显式调用renderer.setSize(width, height),否则 canvas 缓冲区大小与 CSS 显示尺寸错位,出现拉伸或裁剪 - 若页面有多个
WebGLRenderer实例(如分屏 3D),每个必须使用独立canvas,共用 canvas 会导致上下文冲突,报错INVALID_OPERATION: makeCurrent: context is lost
THREE.Mesh 材质选错会导致模型不可见
初学者最常踩的坑:用 THREE.MeshBasicMaterial 渲染带光照的场景,或用 THREE.MeshStandardMaterial 却没加光源。关键区别:
立即学习“前端免费学习笔记(深入)”;
-
MeshBasicMaterial:不响应光照,适合 UI 图标、线框调试、纯色几何体;wireframe: true可快速验证几何体结构 -
MeshNormalMaterial:用于调试法线方向,颜色映射表面朝向,无需光源 -
MeshStandardMaterial:真实感渲染主力,但必须搭配THREE.DirectionalLight或THREE.AmbientLight,否则全黑;且需确保模型有法线(geometry.computeVertexNormals()对自定义几何体必要)
动画循环中 requestAnimationFrame 的实际陷阱
看似简单的 requestAnimationFrame(animate) 循环,容易引发性能和同步问题:
- 不要在
animate函数内重复创建对象(如每次新建THREE.Vector3),应复用已有实例,否则触发频繁 GC,帧率骤降 - 旋转/缩放等属性更新后,若未调用
mesh.rotation.x += 0.01类操作,而仅修改mesh.matrix,需手动设mesh.matrixAutoUpdate = false并在渲染前调用mesh.updateMatrix(),否则变换无效 - 多物体动画不同步?检查是否所有
rotation增量都基于同一时间源(如performance.now()),避免用+= 0.01这类固定步长——帧率波动时会忽快忽慢
Three.js 的“简化”不是掩盖复杂性,而是把 WebGL 的硬性约束转化为可调试的对象状态;一旦遇到黑屏、闪烁、Z-fighting 或材质丢失,第一反应不该是换库,而是查 renderer.info.memory.geometries 是否爆增、scene.children 是否误删、或 camera.near 是否设成了 0(直接导致近裁剪面失效)。



















