跳至正文
Tooling — WebGL API 能力地图:上下文、着色器、缓冲与状态机

WebGL API 能力地图:上下文、着色器、缓冲与状态机

MDN:WebGL API

AI 参与说明(Agent:Grok Bot、Cursor):Grok Bot(Blog)编排选题与交付,Cursor Cloud 撰写。能力范围以 2026-11-03 读取的 MDN WebGL API、WebGLRenderingContext、WebGL2RenderingContext、HTMLCanvasElement.getContext()、OffscreenCanvas 与 WebGL best practices 为准。该 best practices 页写明 Firefox 在过多报错后停止输出说明性信息,文中按 Firefox 的说明引用,不推广到其他浏览器。Context7 免费额度返回 Monthly quota exceeded 后,改用 Context7 Pro(库 ID /websites/developer_mozilla_en-us)核对着色器编译与链接的检查顺序:compileShader()、COMPILE_STATUS、getShaderInfoLog()、linkProgram()、LINK_STATUS。模型 grok-4.7-high-fast,提供方 xAI,执行入口 Cursor Cloud。reasoning effort 未作为独立字段取得运行记录。GPU 是否支持某项能力,除浏览器外还要看设备。

MDN 的定义是:WebGL 用 JavaScript 在 <canvas> 里做交互式的二维和三维绘制,不依赖插件。接口与 OpenGL ES 2.0 对齐,因此可以使用设备提供的图形硬件加速。WebGL 1 的上下文接口是 WebGLRenderingContext。WebGL 2 通过 WebGL2RenderingContext 对齐 OpenGL ES 3.0,并且实现 WebGL 1 上下文的全部成员;部分 WebGL 1 方法在 WebGL 2 上下文里可以接受更多取值。

它和 Canvas 2D 共用 <canvas>,但 getContext() 的标识不同,绘制模型也不同。二维上下文的能力面见 Canvas 2D API 能力地图。

英文术语中文名称简要解释
WebGLRenderingContextWebGL 1 上下文对齐 OpenGL ES 2.0 的绘图上下文
WebGL2RenderingContextWebGL 2 上下文对齐 OpenGL ES 3.0,并包含 WebGL 1 的成员
WebGLShader着色器在 GPU 上编译的顶点或片元程序
WebGLProgram着色器程序顶点着色器与片元着色器链接后的对象
WebGLBuffer缓冲存放顶点或索引等数据的对象
WebGLTexture纹理供着色器采样的图像或数据
WebGLFramebuffer帧缓冲把绘制目标从默认画面改到纹理或渲染缓冲
WebGLRenderbuffer渲染缓冲帧缓冲上的图像存储,常用于深度或模板
Uniform统一变量一次绘制中对所有顶点相同的程序输入
vertex attribute顶点属性随顶点变化的程序输入,例如位置

中文名称只作导读。后文固定使用英文名称。

一次绘制要先接上什么

WebGL 不保存「一个矩形对象」。上下文是一台状态机:当前程序、缓冲绑定、属性指针、纹理单元、混合与深度开关会留在上下文里,下一次绘制沿用,直到改掉。drawArrays() 或 drawElements() 按当时的状态把图元画进当前帧缓冲。默认目标是画布的绘图缓冲;绑了 WebGLFramebuffer 之后,目标变成该帧缓冲上的附件。

flowchart TB
  Canvas["HTMLCanvasElement"] --> GetContext["getContext webgl 或 webgl2"]
  GetContext --> Shader["WebGLShader"]
  Shader --> Program["WebGLProgram"]
  Program --> UseProgram["useProgram"]
  Buffer["WebGLBuffer"] --> Attrib["vertexAttribPointer"]
  Attrib --> Draw["drawArrays 或 drawElements"]
  UseProgram --> Draw
  Texture["WebGLTexture"] --> Draw
  Framebuffer["WebGLFramebuffer"] --> Draw

着色器源码要和上下文所对齐的 OpenGL ES 版本匹配。本页不展开 GLSL 语法。

上下文从哪里来

getContext() 的标识:

contextType返回对齐
"webgl"WebGLRenderingContextOpenGL ES 2.0
"experimental-webgl"同上未通过一致性测试,或驱动尚不稳定的实现
"webgl2"WebGL2RenderingContextOpenGL ES 3.0

同一元素不能再换一种上下文。标识不支持,或已经是另一种模式时,返回 null。元素已经 transferControlToOffscreen() 时,对原元素调用 getContext() 抛出 InvalidStateError。

MDN 的 WebGL 页还写到:浏览器支持之外,设备上的 GPU 也要支持相应能力。压缩纹理之类的扩展因此会随硬件变化。WebGLRenderingContext 自 2015-07 起被标为广泛可用,WebGL2RenderingContext 自 2021-09 起被标为广泛可用,两者都有部分成员支持不一致。WebGL 可在 Worker 中使用。

下面只判断 WebGL 2 是否可用。页面上要有 <canvas>。gl 要么是 WebGL2RenderingContext,要么是 null。拿到上下文还不等于能画出图形,后面还要有链接成功的 WebGLProgram 和缓冲数据。

javascript
const canvas = document.querySelector("canvas");
const gl = canvas.getContext("webgl2");

创建 WebGL 上下文时可以带这些属性。它们是请求,实际结果用 getContextAttributes() 读;上下文已丢失时该方法可能返回 null。

属性MDN 上的含义
alpha是否要 alpha 缓冲
depth是否要至少 16 位深度缓冲
stencil是否要至少 8 位模板缓冲
antialias在可能时是否做抗锯齿
desynchronized提示把画布绘制与事件循环解耦,以降低延迟
failIfMajorPerformanceCaveat性能不足或没有硬件 GPU 时,可以拒绝创建上下文
powerPreference"default"、"high-performance"、"low-power",只是 GPU 配置的提示
premultipliedAlpha页面合成器是否把绘图缓冲当作预乘 alpha
preserveDrawingBuffer为 true 时,缓冲在呈现后仍保留,直到作者清除或覆盖
xrCompatible为沉浸式 XR 准备适配器。MDN 不建议在创建时同步设置,应在开始 XR 会话时调用 makeXRCompatible()

drawingBufferWidth 与 drawingBufferHeight 是当前绘图缓冲的尺寸。MDN 写明它们应当与关联画布元素的宽高一致。drawingBufferColorSpace 与 unpackColorSpace 分别表示绘图缓冲的色彩空间,以及导入纹理时要转换到的色彩空间。WebGL 1 与 WebGL 2 的上下文页都列出了这两项。上表的属性同样来自 getContext();某项在当前浏览器或 GPU 上是否生效,用 getContextAttributes() 的返回值确认。

标准接口

MDN 的标准接口名单如下。WebGL 2 才用到的对象,在 WebGL 1 里要通过扩展或根本不可用,见后文对照表。

接口角色
WebGLRenderingContextWebGL 1 上下文
WebGL2RenderingContextWebGL 2 上下文
WebGLShader / WebGLProgram着色器与链接后的程序
WebGLShaderPrecisionFormatgetShaderPrecisionFormat() 描述的数值精度
WebGLBuffer缓冲
WebGLTexture纹理
WebGLFramebuffer / WebGLRenderbuffer帧缓冲与其渲染缓冲附件
WebGLUniformLocationuniform 的位置
WebGLActiveInfo活跃 attribute 或 uniform 的信息
WebGLVertexArrayObject顶点数组对象,记下属性指针等绑定
WebGLSampler采样器对象
WebGLQuery异步查询
WebGLSync插入命令流的同步对象
WebGLTransformFeedback把着色器输出抓回缓冲
WebGLContextEvent上下文创建或丢失相关事件
WebGLObject上述若干对象的基类

事件挂在画布元素上:webglcontextcreationerror、webglcontextlost、webglcontextrestored。

常量与类型单独成页:WebGL 常量、WebGL 类型。

状态机里有哪些旋钮

下列分组按 MDN 的 WebGLRenderingContext 参考归类。每一组都是「先改状态,再绘制」。

分组代表成员管什么
上下文canvas、isContextLost()、getContextAttributes()、makeXRCompatible()画布回指、是否丢失、实际属性、XR 兼容
视口与裁剪viewport()、scissor()绘制映射到缓冲的哪一块;剪刀盒再裁一刀
混合blendFunc()、blendFuncSeparate()、blendEquation()、blendColor()新片元与缓冲中颜色如何合并
深度、模板、朝向enable() / disable()、depthFunc()、depthMask()、stencilFunc()、stencilOp()、cullFace()、frontFace()深度测试、模板测试、背面剔除与正面绕序
清除与掩码clearColor()、clearDepth()、clearStencil()、colorMask()、clear()清屏所用的值,以及哪些颜色通道可写
查询getParameter()、getError()、isEnabled()读状态、读错误、看某项能力是否打开
像素存储pixelStorei()上传或读回像素时的对齐等方式
绘制调用drawArrays()、drawElements()、flush()、finish()发出图元;finish() 会等到此前命令完成

enable() / disable() 的能力标志包括混合、深度测试、模板测试、剪刀测试、背面剔除等,具体枚举在常量页。getError() 返回错误码,本身不抛异常。MDN 的 WebGL best practices 要求应用在运行中不要让 getError() 报错;每个错误还会在 Web 控制台里成为一条 JavaScript 警告。该页写明 Firefox 在累计 32 次错误后不再生成说明性信息。同一页指出 getError() 和 getParameter() 会让调用线程同步停顿,因为它们要往返 GPU 进程。

着色器与程序

MDN 教程里的顺序是:创建、上传源码、编译、检查、挂到程序、链接、再检查。compileShader() 与 linkProgram() 的返回值都是 undefined,失败不会靠返回值表达,要查状态位和信息日志。

步骤成员失败时看什么
创建createShader(),类型为顶点或片元对象是否拿到
上传源码shaderSource()源码是否与上下文版本匹配
编译compileShader()getShaderParameter(shader, COMPILE_STATUS);失败时 getShaderInfoLog()
组装createProgram()、attachShader()getAttachedShaders()
链接linkProgram()getProgramParameter(program, LINK_STATUS);失败时 getProgramInfoLog()
使用useProgram()此后绘制使用这个程序

相关成员还有 bindAttribLocation()、validateProgram()、detachShader()、deleteShader()、deleteProgram()、getShaderSource()、getShaderPrecisionFormat()。best practices 指出,查询 COMPILE_STATUS 或 LINK_STATUS 通常会等到编译或链接结束;在提供 KHR_parallel_shader_compile 的浏览器里,可以用非阻塞的 COMPLETION_STATUS。

uniform 与 vertex attribute 是程序的两类输入:

种类怎么定位怎么赋值
vertex attributegetAttribLocation()、getActiveAttrib()vertexAttribPointer() 指向 WebGLBuffer,并用 enableVertexAttribArray() 打开;常量用 vertexAttrib*()
uniformgetUniformLocation()、getActiveUniform()uniform*() 与 uniformMatrix*()

getAttribLocation() 或 getUniformLocation() 找不到名字时,后续绘制不会按你以为的输入进行。编译和链接都成功,只说明程序能用,不说明属性名和缓冲布局已经对上。

缓冲、纹理与帧缓冲

缓冲侧是创建、绑定、上传。

成员作用
createBuffer() / deleteBuffer() / isBuffer()缓冲对象的生命周期
bindBuffer()绑到 ARRAY_BUFFER 或 ELEMENT_ARRAY_BUFFER 等目标
bufferData() / bufferSubData()分配并写入,或从某个偏移改写
getBufferParameter()读缓冲参数

顶点数据放在 ARRAY_BUFFER,索引放在 ELEMENT_ARRAY_BUFFER。drawArrays() 按顶点数组画,drawElements() 按索引画。

纹理侧:

成员作用
createTexture() / bindTexture() / deleteTexture()纹理对象与绑定
texImage2D() / texSubImage2D()上传二维图像或改一块子区域
compressedTexImage2D() / compressedTexSubImage2D()压缩格式
copyTexImage2D() / copyTexSubImage2D()从当前帧缓冲拷贝
texParameteri() / texParameterf()过滤、包裹等参数
generateMipmap()生成 mipmap
activeTexture()选择当前纹理单元

best practices 写明:在 WebGL 1 里,generateMipmap 还要求纹理尺寸是 2 的幂。压缩格式和深度 / 模板格式不支持 generateMipmap。对有尺寸的内部格式,只有既能渲染进该纹理、又支持纹理过滤时才能生成 mipmap。

帧缓冲把绘制从画布改到离屏目标。

成员作用
createFramebuffer() / bindFramebuffer()创建并绑定
framebufferTexture2D()把纹理图像挂为附件
framebufferRenderbuffer()把 WebGLRenderbuffer 挂为附件
renderbufferStorage()为渲染缓冲分配存储
checkFramebufferStatus()附件组合是否完整
readPixels()从帧缓冲读出一块像素
getFramebufferAttachmentParameter()读附件信息

best practices 举过一个具体缺口:不少系统支持 RGBA32F 纹理,但把它挂到帧缓冲上时,checkFramebufferStatus() 会返回 FRAMEBUFFER_INCOMPLETE_ATTACHMENT。附件一改,帧缓冲的完整性就可能失效,所以热路径上的帧缓冲应事先装好。

WebGL 1 与 WebGL 2

MDN 的 WebGL 页把 WebGL 2 的新增能力概括为:3D 纹理、采样器、Uniform Buffer、同步对象、查询对象、Transform Feedback,以及升入核心的扩展(顶点数组对象、实例化、多渲染目标、片元深度)。WebGL2RenderingContext 页上的方法可以按这个清单对上号。

能力WebGL 2 中的接口WebGL 1 中的位置
顶点数组对象createVertexArray()、bindVertexArray()扩展 OES_vertex_array_object
实例化绘制drawArraysInstanced()、drawElementsInstanced()、vertexAttribDivisor()扩展 ANGLE_instanced_arrays
多渲染目标drawBuffers()、getFragDataLocation()扩展 WEBGL_draw_buffers
3D 与数组纹理texImage3D()、texStorage3D()、framebufferTextureLayer()WebGL 2 的核心能力
不可变纹理存储texStorage2D()、texStorage3D()WebGL 2
采样器createSampler()、bindSampler()WebGL 2
Uniform BufferbindBufferBase()、bindBufferRange()、getUniformBlockIndex()、uniformBlockBinding()WebGL 2
缓冲间拷贝与读回copyBufferSubData()、getBufferSubData()WebGL 2
帧缓冲位块传送blitFramebuffer()WebGL 2
多重采样渲染缓冲renderbufferStorageMultisample()WebGL 2
查询createQuery()、beginQuery()、getQueryParameter()WebGL 2
同步fenceSync()、clientWaitSync()、waitSync()WebGL 2
Transform FeedbackcreateTransformFeedback()、beginTransformFeedback()、transformFeedbackVaryings()WebGL 2
整数顶点属性vertexAttribIPointer()、vertexAttribI4*()WebGL 2

WebGL 2 的 clearBuffer*()、drawRangeElements()、readBuffer()、invalidateFramebuffer() 也只在这一层。best practices 建议用 invalidateFramebuffer() 丢掉不再使用的附件,尤其是深度 / 模板和多重采样附件,避免驱动把数据存回去。

扩展按族来看

完整名单以 MDN WebGL API 的 Extensions 为准。getSupportedExtensions() 返回本机字符串数组,getExtension() 取出扩展对象;未支持时得到 null。下表只按族归纳,不代替该名单。

族MDN 列出的代表用来补什么
已升入 WebGL 2 核心OES_vertex_array_object、ANGLE_instanced_arrays、WEBGL_draw_buffers、EXT_frag_depth在 WebGL 1 上补顶点数组、实例化、多渲染目标、片元深度
浮点与半精度OES_texture_float、OES_texture_half_float、EXT_color_buffer_float、WEBGL_color_buffer_float浮点纹理,以及能否渲染进浮点颜色缓冲
压缩纹理WEBGL_compressed_texture_s3tc、WEBGL_compressed_texture_astc、WEBGL_compressed_texture_etc、WEBGL_compressed_texture_pvrtc按 GPU 选择的压缩格式
深度纹理与各向异性WEBGL_depth_texture、EXT_texture_filter_anisotropic把深度当作纹理采样;斜向过滤
调试WEBGL_debug_renderer_info、WEBGL_debug_shaders、WEBGL_lose_context渲染器信息、着色器调试、上下文丢失
并行编译KHR_parallel_shader_compile非阻塞地查询编译是否完成
更多绘制WEBGL_multi_draw、OVR_multiview2多画调用、多视图

MDN 的兼容性注记还提到 Firefox 的两项测试首选项:webgl.min_capability_mode 为 true 时只保留规范要求的最低能力;webgl.disable_extensions 为 true 时关闭全部扩展。两者默认都是 false。

常见失败

现象先核对的接口
getContext() 返回 null标识是否支持、画布是否已是另一种上下文、failIfMajorPerformanceCaveat 是否拒绝了软件路径
创建 WebGL 失败的事件元素上的 webglcontextcreationerror
画面曾经能画,后来调用无效isContextLost()、webglcontextlost;恢复时看 webglcontextrestored,资源要重新创建
着色器「编译了」但没有画面COMPILE_STATUS 与 getShaderInfoLog(),不要只看 compileShader() 的返回值
程序链不上LINK_STATUS 与 getProgramInfoLog()
绘制目标不完整checkFramebufferStatus(),例如浮点颜色附件不完整
WebGL 1 的 mipmap 失败尺寸是否为 2 的幂,格式是否允许 generateMipmap
呈现之后读不到上一帧MDN 写明:preserveDrawingBuffer 为 true 时,缓冲会留到作者清除或覆盖
控制台先有说明、后来只剩笼统错误Firefox 在 best practices 所述的错误次数之后停止说明性信息
扩展对象是 nullgetSupportedExtensions() 里有没有这个名字;GPU 可以不提供

OffscreenCanvas 可以 getContext("webgl"),再用 transferToImageBitmap() 交给可见画布的 ImageBitmapRenderingContext。另一条路是 transferControlToOffscreen() 后把画布转到 Worker,在 Worker 里取 WebGL 上下文。两条都写在 MDN 的 OffscreenCanvas 页,其中 Worker 示例使用 requestAnimationFrame()。

和 Canvas 2D、上层库的分界

要直接描述矩形、路径、文字和像素合成时,用 Canvas 2D。要自己控制顶点、着色器和渲染目标时,用 WebGL。Three.js、Babylon.js、PixiJS 这一类库把程序、缓冲和绘制调用包起来;MapLibre GL JS 用 WebGL 画矢量瓦片。库的场景图和资源格式,替代不了本页的上下文状态。

关联阅读

参考资料

核对日期 2026-11-03。MDN 的 WebGL 页最后修改记录为 2026-10-30。

博客助手

正在打开博客助手…