---
title: "P1 WebGL生态地图与核心API"
author: "Perrin Yong"
author_profile: https://www.pystone.net/profile/
published_by: "Perrin Yong"
canonical: https://www.pystone.net/notes/webgl-ecosystem-core-api/
type: note
content_role: unspecified
visibility: public
id_stability: rename-stable
source_path: "10-计算机、信息技术与工程/05-游戏图形与运行时/WebGL/P1 WebGL生态地图与核心API.md"
content_hash: 9c1e35062243c96fe031816575524b6f3360e4ebc1cc4677c05f45e4e1d1ca5c
knowledge_version: 224c990773de.5fa8af6e39fa
site_commit: 224c990773de166d23a886306577dd90379529ce
notes_commit: 5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a
---
[WebGL](https://www.khronos.org/webgl/) enables web content to use an API based on [OpenGL ES](https://www.khronos.org/opengles/) 2.0 to perform 3D rendering in an HTML `<canvas>` in browsers that support it without the use of plug-ins.

WebGL programs consist of control code written in JavaScript and special effects code (shader code) that is executed on a computer's Graphics Processing Unit (GPU).

WebGL elements can be mixed with other HTML elements and composited with other parts of the page or page background.
# P1 WebGL生态地图与核心API
### 0 核心原理

状态机:
WebGL is really just an API to run shaders. The only functions that actually write pixels are `gl.clear`, `gl.drawArrays` and `gl.drawElements`. That's it! All other API calls just setup internal state for when those 3 functions are called.

顶点和片段Shader:
WebGL only cares about 2 things: clip space coordinates and colors. Your job as a programmer using WebGL is to provide WebGL with those 2 things. You provide your 2 "shaders" to do this. A Vertex shader which provides the clip space coordinates, and a fragment shader that provides the color.
![assets/image-20250512232206264.png](/media/86912608e0956a6835e5.png)


---

### 1 浏览器‑GPU 渲染链

```text
JS 源码 ─┐
          ↓  (1) JavaScript 解释/编译 (V8/SpiderMonkey…)
 **WebGL API 调用**  ──────────▶  (2) WebGL 驱动层
                                         │   把状态、顶点、uniform 等写入
                                         │   GPU Command Buffer
                                         ▼
                                  (3) GPU 驱动
                                         │   真正执行顶点 / 光栅 / 片元着色器
                                         ▼
                                  (4) 帧缓冲 → 屏幕
```

* **DOM 树** 并不参与这条链；WebGL 只依赖 `<canvas>` 提供的像素缓冲。
* 调用链中能被你直接编写的只有：

  1. **JavaScript 逻辑**（WebGL API）
  2. **GLSL 着色器**（GPU 端程序）

---

### 2 WebGL 与 OpenGL ES 关系

* **WebGL 1.0 ≈ OpenGL ES 2.0**（固定管线消失，全部靠顶点/片元着色器）。
* **WebGL 2.0 ≈ OpenGL ES 3.0**，带来：

  * **VAO**（Vertex Array Object）
  * **UBO**（Uniform Buffer Object）
  * **Instanced Draws**
  * 多渲染目标（MRT）等高级特性。
* 判断浏览器支持：

  ```js
  const gl2 = canvas.getContext('webgl2');   // null ⇒ 只支持 WebGL1
  ```

  ([MDN Web Docs][1])

---

### 3 GLSL ES 语法要点

| 关键字                        | 作用          | WebGL1 vs WebGL2                     |
| -------------------------- | ----------- | ------------------------------------ |
| `attribute`                | 逐顶点输入       | **仅 WebGL1**；在 WebGL2 用 `in`         |
| `uniform`                  | 所有顶点/片元共享参数 | 相同                                   |
| `varying`                  | 顶点→片元插值     | WebGL1 用 `varying`，WebGL2 用 `out/in` |
| `precision mediump float;` | 片元默认精度      | 片元着色器必须指定精度                          |

GLSL 程序在运行前 **编译 + 链接**，否则 GPU 无法执行。([The Khronos Group][2])

---

### 4 四步搞定最小渲染

1. **获取 WebGL Context**

   ```js
   const gl = canvas.getContext('webgl');     // 或 'webgl2'
   if (!gl) throw 'WebGL unsupported!';
   ```
2. **编译着色器**

   ```js
   const vs = gl.createShader(gl.VERTEX_SHADER);
   gl.shaderSource(vs, vertexSource);
   gl.compileShader(vs);
   ```

   相同流程对片元着色器 (`gl.FRAGMENT_SHADER`)。
3. **链接程序并激活**

   ```js
   const prog = gl.createProgram();
   gl.attachShader(prog, vs);  gl.attachShader(prog, fs);
   gl.linkProgram(prog);  gl.useProgram(prog);
   ```
4. **上传数据 + 绘制**

   ```js
   const buf = gl.createBuffer();
   gl.bindBuffer(gl.ARRAY_BUFFER, buf);
   gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([...]), gl.STATIC_DRAW);

   const loc = gl.getAttribLocation(prog, 'aPos');
   gl.enableVertexAttribArray(loc);
   gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);

   gl.clearColor(0,0,0,1); gl.clear(gl.COLOR_BUFFER_BIT);
   gl.drawArrays(gl.TRIANGLES, 0, 3);
   ```

详细代码见 §6。流程出自 MDN *Getting Started with WebGL* ([MDN Web Docs][3])

---

### 5 环境配置 & 操作方法

1. **编辑器**：VS Code
2. **本地服务器**：安装扩展“Live Server”，右键 HTML → *Open with Live Server*（避免跨域和文件协议限制）。
3. **浏览器**：Chrome/Edge 最新版；开启 DevTools > Rendering > *WebGL errors and warnings* 选项可即时捕获 GL 报错。([Chrome for Developers][4])

---

### 6 三角形完整示例 + 行内注释

```html
<meta charset="utf-8">
<canvas id="c" width="640" height="480"></canvas>
<script>
/// 1. 取 context ————————————————————————
const gl = document.getElementById('c').getContext('webgl');
if (!gl) { alert('WebGL unsupported'); throw 'no gl'; }

/// 2. 写 GLSL 源码 ————————————————————————
const vsSrc = `                 // 顶点着色器: 把顶点坐标直接送裁剪空间
attribute vec2 aPos;
void main() { gl_Position = vec4(aPos, 0.0, 1.0); }`;

const fsSrc = `                 // 片元着色器: 每个像素涂亮红色
precision mediump float;
void main() { gl_FragColor = vec4(1.0, 0.2, 0.2, 1.0); }`;

/// 3. 编译 & 链接 ————————————————————————
function compile(src,type){
  const s = gl.createShader(type);
  gl.shaderSource(s, src);  gl.compileShader(s);
  if(!gl.getShaderParameter(s, gl.COMPILE_STATUS))
      console.error(gl.getShaderInfoLog(s));
  return s;
}
const prog = gl.createProgram();
gl.attachShader(prog, compile(vsSrc, gl.VERTEX_SHADER));
gl.attachShader(prog, compile(fsSrc, gl.FRAGMENT_SHADER));
gl.linkProgram(prog); gl.useProgram(prog);

/// 4. 上传顶点 ————————————————————————
const buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER,
  new Float32Array([ 0,0.8,  -0.8,-0.8,  0.8,-0.8 ]),
  gl.STATIC_DRAW);

const loc = gl.getAttribLocation(prog, 'aPos');
gl.enableVertexAttribArray(loc);
gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);

/// 5. 清屏并绘制 ————————————————————————
gl.clearColor(0,0,0,1);       // 背景设黑
gl.clear(gl.COLOR_BUFFER_BIT); // 清颜色缓冲
gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>
```

运行后看到红色三角即表示管线打通。

---

### 7 DevTools 调试要领

1. **Sources ▶ WebGL**

   * *Shaders* 节点列出已编译 GLSL；点击可查看源码、uniform 值。
   * *Calls* 面板统计本帧 WebGL API 调用数量。
2. **Console**

   ```js
   gl.getParameter(gl.VERSION);      // "WebGL 1.0 ..." or "WebGL 2.0 ..."
   gl.getError();                    // 返回错误码 0 OK
   ```
3. **Performance ▶ Frames**

   * 录制后展开一帧，可见 CPU script vs GPU raster 时间分布。

详见 Chrome DevTools Rendering & Performance 文档 ([Chrome for Developers][4])

---


### Reference

[1]: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext?utm_source=chatgpt.com "WebGLRenderingContext - Web APIs | MDN - MDN Web Docs"
[2]: https://www.khronos.org/opengl/wiki/Fragment_Shader?utm_source=chatgpt.com "Fragment Shader - OpenGL Wiki - The Khronos Group"
[3]: https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Getting_started_with_WebGL?utm_source=chatgpt.com "Getting started with WebGL - Web APIs | MDN - MDN Web Docs"
[4]: https://developer.chrome.com/docs/devtools/rendering/performance/?utm_source=chatgpt.com "Discover issues with rendering performance - Chrome DevTools"
[5]: https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_lose_context?utm_source=chatgpt.com "WEBGL_lose_context extension - Web APIs | MDN - MDN Web Docs"
[6]: https://webglfundamentals.org/docs/?utm_source=chatgpt.com "Home - Documentation - WebGL Fundamentals"


## 相关工具

JavaScript、HTML 和 CSS在线编辑、测试： https://jsfiddle.net/

three 学习引导GPT： https://chatgpt.com/g/g-jGjqAMvED-three-js-mentor/


## 调试

```text
在 VS Code 中安装 Live Server 插件。
右键点击 index.html，选择 “Open with Live Server”。
VS Code 将在某个端口（默认 5500）启动本地服务器。
```
