跳到主要内容

WebGL-vs-WebGPU-vs-Canvas2D

1. 问题先分类,再选表面

你真正要的优先不要先上
可命中、可读屏、可复制文本的图形 UIDOM / SVG任何 canvas
笔刷、混合模式烘焙、少量像素滤镜Canvas 2D为一条水印开着色器
万级实例、点精灵、每像素公式、三维网格WebGL22D 里 fillRect 硬撑
计算着色、更干净的资源生命周期WebGPU(探测到 adapter)假装 2026 年可以删 WebGL

Canvas 2D 适用,当 帧的真相是像素。SVG 适用,当 帧的真相是文档节点。WebGL / WebGPU 适用,当 帧的真相是 GPU 程序

混用两张 canvas 是生产常态:GL 画密度,2D / DOM 画轴、tooltip、表单。getContext 在同一元素上互斥,见 上下文生命周期

2. Canvas 2D:够用就别上 GPU

适用

  • 百~千级 path,每对象很「像素」
  • 导出模型简单:读 backing store
  • 和视频帧、ImageBitmap、Worker 同一套位图

死线(碰到就该换或叠一层)

  • 实例过万还要每帧独立变换:2D 同步光栅打不过
  • 每像素 LUT / 扭曲 / 多 pass 辉光:需要 fragment
  • 要深度、网格、PBR:不是 2D 的活

3. WebGL2:生产默认光栅器

生产创建只认 webgl2。它解决的是 draw call + buffer + 纹理 在现有浏览器上的最大公约数。

适用: 散点、粒子、后处理、瓦片、视频纹理、简单三维查看。移动端与企业 WebView 的基线仍在这里。

不适用:

  • 把它当 DOM。文本、表单、读屏叠 SVG / HTML,见 与 2D 叠层
  • 需要可移植 compute。WebGL2 能 ping-pong FBO 冒充,但不是计算 API
  • requestAdapter() 已成功且产品就是计算管线:直接 WebGPU,GL 当降级

4. WebGPU:探测之后用,不是许可证

WebGPU 更接近现代 GPU:显式 pass、buffer 生命周期、compute。navigator.gpu.requestAdapter()null 是产品路径。

适用: 直方图、卷积、粒子积分、需要 compute 的图像处理;团队已能承受降级面。

不适用: 「先写 WebGPU 再考虑 GL」。Safari / Firefox / Android 覆盖面仍要当二等公民,见 07。安全上下文是硬条件。

5. 一个可执行的判定流程

type Surface = "css" | "svg" | "canvas2d" | "webgl2" | "webgpu";

export function chooseSurface(input: {
truth: "document" | "pixels" | "gpu-program";
interactiveText: boolean;
pixelBrush: boolean;
needsCompute: boolean;
instanceCount: number;
adapterOk: boolean;
}): Surface {
if (input.interactiveText || input.truth === "document") {
return "svg";
}
if (input.pixelBrush || input.truth === "pixels") {
return "canvas2d";
}
if (input.truth !== "gpu-program" && input.instanceCount < 8_000) {
return "canvas2d";
}
if (input.needsCompute && input.adapterOk) {
return "webgpu";
}
return "webgl2";
}

instanceCount 是每帧要独立更新的图元数,不是场景里存在的总节点。静态一万个 SVG path 仍可能比每帧重绘一千个 GPU 实例更合适——测过再翻案。adapterOk 必须是运行时探测,不要写死浏览器名单。

两张 canvas 叠层时,判定函数可以返回两次:场景 webgl2,chrome canvas2d 或 DOM。不要为了「只用一个元素」把 UI 画进 shader。

6. 失败形态

症状选错了什么
编辑器做不出选择 / 读屏用 GL 替代了文档
粒子 2D 分桶后仍 20fps该 GPU 还在 2D
同一元素 getContext 返回 null违反单例,该两张叠
上了 WebGPU 白屏requestAdapter()null 没有 GL 降级
只要一个 blur 却开了后处理栈该 2D filter 或预烘焙

权威资料

核对日期:2026-08-26