绝大多数前端开发者无需直接使用原生WebGL,因其初始化成本高、错误反馈弱、跨浏览器行为不一致,而Three.js封装了底层复杂性,100行内即可实现兼容性好、调试便捷的3D预览。

直接用 Three.js,别碰原生 WebGL —— 除非你明确需要控制着色器或做底层优化。绝大多数在线 3D 预览场景(产品展示、数据可视化、建筑模型)用 Three.js 能在 100 行内跑起来,且兼容性、调试体验和加载效率都远胜手写 WebGL。
为什么不用原生 WebGL 写在线预览?
原生 WebGL 的初始化成本高、错误反馈弱、跨浏览器行为不一致,尤其在「在线预览」这类需快速交付、多端适配的场景里,容易卡在:gl.getShaderParameter(..., gl.COMPILE_STATUS) 返回 false 却不报具体 GLSL 错误、gl.drawArrays 前忘记绑定 buffer、gl.clearColor 设置后没调 gl.clear 导致画面残留等。这些不是逻辑问题,是样板代码里的隐性陷阱。
而 Three.js 把这些封装进 WebGLRenderer 初始化、Mesh 自动管理 attribute 和 uniform、错误统一抛到 console,省下的时间够你调好光照和材质。
Three.js 加载 glTF 模型时最常见的白屏原因
在线预览最常用的是 glTF 格式(.gltf 或 .glb),但白屏往往不是模型问题,而是加载链路断在中间:
立即学习“前端免费学习笔记(深入)”;
-
GLTFLoader没正确引入:CDN 地址要匹配版本,比如https://cdn.jsdelivr.net/npm/three@0.152.2/examples/jsm/loaders/GLTFLoader.js,旧版用js/loaders路径会 404 - 模型路径跨域:本地 file:// 打开 HTML 时,浏览器禁止读取本地文件;必须走 http(s) 服务,或用
http-server本地起一个 - 没处理
scene.add(mesh)后的 scale / position:很多导出的 glTF 模型单位是米,但画布默认视角只看到 1 单位范围,结果模型“存在但看不见”——加一句mesh.scale.set(0.1, 0.1, 0.1)就能出来 - 漏掉
renderer.render(scene, camera)在动画循环里:只初始化不渲染,自然黑屏
如何让 WebGL 预览在低端设备上不卡顿
性能瓶颈通常不在 GPU,而在 JavaScript 层面的冗余计算和频繁重绘:
- 禁用
renderer.shadowMap.enabled = true:阴影计算开销大,预览场景多数不需要真实阴影,用MeshStandardMaterial的roughness和metalness模拟质感更轻量 - 限制帧率:用
requestAnimationFrame但加 throttle,比如每 16ms(60fps)强制跳过一半帧,改成 30fps:“if (performance.now() - lastRender > 33) { renderer.render(...); lastRender = performance.now(); }” - 纹理压缩:上传的贴图尽量用
.jpg替代.png,宽高必须是 2 的幂(如 1024×1024),否则 WebGL 会自动缩放并触发警告 - 避免每帧修改材质:不要在
animate()里反复设material.color.setHex(0xff0000),提前创建多个材质复用
真正难的不是让模型转起来,而是判断什么时候该降级:比如检测到 navigator.hardwareConcurrency 或 <code>screen.width ,就自动关闭环境光、简化几何体、停掉旋转动画——这些逻辑比写着色器更影响用户是否愿意多看两秒。



















