自研vsThree-Pixi-Babylon
缺的不是 API,是 场景图、资源生命周期、GLTF 生态、相机与灯光。库能买到这些,也会把你锁进它的对象模型和渲染循环。GPU 程序仍是真相:用了引擎不等于可以不懂 NDC、DPR、taint、上下文丢失。
新项目不要「学完教程就自研引擎」。立方体 demo 证明你会写 shader,不证明你能做材质图、蒙皮、 tonemap、资源释放和三年生态。
1. 怎么选
| 需求 | 倾向 |
|---|---|
| 散点 / 粒子 / 全屏后处理,自己已有 CPU 场景 | 自研 WebGL2(或探测后的 WebGPU) |
| 大量 2D 精灵、骨骼、粒子游戏 | Pixi(偏 2D WebGL / WebGPU,不是 CanvasRenderingContext2D) |
| GLTF、PBR、灯光、三维查看 / 3D 游戏壳 | Three 或 Babylon |
| 必须无障碍、可选文本 | 不要这些库当 DOM |
| 只要一个模型转一转 | 引擎;不要自研完整 PBR |
type GpuStack = "custom" | "pixi" | "three" | "babylon";
export function chooseGpuStack(input: {
kind: "scatter" | "particles" | "postfx" | "sprite-2d" | "gltf-viewer" | "scene-3d";
hasCpuScene: boolean;
wantsBatteries: boolean;
}): GpuStack {
if (input.kind === "gltf-viewer" || input.kind === "scene-3d") {
return input.wantsBatteries ? "babylon" : "three";
}
if (input.kind === "sprite-2d") return "pixi";
if (input.hasCpuScene) return "custom";
if (
input.kind === "scatter" ||
input.kind === "particles" ||
input.kind === "postfx"
) {
return "custom";
}
return "custom";
}
数字和 kind 是信号,不是基准。有现成 CPU 场景图时,换光栅器比换对象模型便宜——这是 Canvas 00 自建 scene 的回报。
2. 各库实际买到什么
PixiJS
渲染器是 WebGL / WebGPU,主场是 2D 精灵、粒子、滤镜 shader。你在本体系学的 VAO / FBO 不能 假装成 2D fill。UI 编辑器硬用 Pixi,会把简单矩形变成纹理图集问题。不要拿它当 Three 的 2D 模式。
Three.js
偏 3D:场景图、相机、灯光、GLTF、社区加载器。生态大。它不替你做产品文档模型,也不替你做撤销。把 mesh.position 当唯一数据源,协作和历史记录会对不上。本体系其它章不绑 Three。
Babylon.js
同样偏 3D,相机 / PBR / Inspector / 加载器更开箱。适合「三维查看器要尽快能看模型」。代价是体积和概念面。和 Three 选一个当 3D 壳,不要两个叠。
有 GLTF / PBR / 蒙皮 / 动画剪辑需求,用引擎。散点、粒子、后处理、瓦片、视频纹理,自研更短:CPU 场景 + 自己的 program,不必买一整套 3D 运行时。
3. 自研时不要重新发明的部分
即使不用引擎,也要有:
- 世界单位 + 相机矩阵(CPU 持有,每帧当 uniform)
- 上下文丢失后的资源表重建
- CORS 干净纹理与导出
- 命令栈撤销(改 CPU 场景,不是改 GPU buffer)
引擎内部仍是 GPU 程序。把「用了 Three」当成「不用懂 drawingBuffer」会在 Retina、taint、丢失上翻车。规则与 08、05 相同。
4. 失败形态
| 症状 | 原因 |
|---|---|
| 为看一个 GLTF 写了半年 PBR | 该用引擎还在自研 |
Pixi 里当 2D 去 getImageData | 那是 GL 读回,成本模型全变 |
| 两个 rAF 循环 | 引擎有自己的 render loop,外面又写了一个 |
| 撤销改了 GPU buffer | 文档不在显存里,丢失/resize 后历史蒸发 |
| 教程结束后开始写引擎 | 缺的是产品层,不是另一份 shader |
权威资料
核对日期:2026-08-26