AI 协作日志

学生 Web 实验作品平台

学号:202412211401016 · 来源:ai-log.md

# 实验一 AI协作记录

> 本文件记录实验过程中的关键人机协作。每次协作均包含自己的判断、
> 实际测试/核验,以及核验后修正的结论。

## AI协作1:理解数据流

### 我的目标

完成任务1前,我想先弄清楚:JavaScript 里的一组数字,究竟经过哪些环节
才变成屏幕上的三角形。我要求 AI 只做解释、不要改我的代码。

### 提示词

> 从 JavaScript 的 Float32Array 到屏幕上出现一个三角形,中间发生了哪些
> 关键步骤?请结合 WebGL2 解释 Buffer、vertexAttribPointer、Vertex
> Shader、光栅化和 Fragment Shader 各自负责什么,不要直接修改我的代码。

### AI关键回答摘要

1. `Float32Array` 是 CPU 内存中按固定步长排列的原始浮点数据;
2. `createBuffer` 在 GPU 侧创建缓冲区,`bindBuffer` 将其设为当前
   `ARRAY_BUFFER`,`bufferData` 把数组数据拷贝上传;
3. `vertexAttribPointer` 告诉 GPU“每个顶点从该 Buffer 取几个 float、
   按什么类型、步长多少”,`enableVertexAttribArray` 打开该属性;
4. Vertex Shader 对每个顶点执行一次,输出裁剪空间位置 `gl_Position`;
5. 图元组装后进入光栅化,把图元拆成片元,并对顶点属性做插值;
6. Fragment Shader 对每个片元执行一次,输出最终颜色到 Canvas。

### 我的判断

AI 的说法与实验指导书第 1 节给出的数据流一致,逻辑上可信。但我最初有
两个地方理解不清:一是以为 `vertexAttribPointer` 会“绑定某个 Buffer
变量”,二是以为 Fragment Shader 拿到的颜色和顶点一一对应、每顶点算一次。
我决定逐项在代码中核验,而不是直接照单全收。

### 验证方法

- 在 [task1.html](task1.html) 中找到两段 Shader,确认 Vertex Shader
  只有 `in vec4 vPosition`、输出 `gl_Position`,Fragment Shader 通过
  `uniform vec4 uColor` 输出 `fColor`;
- 在 [js/task1.js](js/task1.js) 中按顺序找到
  `getContext("webgl2") → initShaders → createBuffer → bindBuffer →
  bufferData → getAttribLocation → vertexAttribPointer →
  enableVertexAttribArray → drawArrays`,与 AI 所说一一对照;
- 对照任务4的代码理解“光栅化插值”,因为任务1是 uniform 单色,
  在三角形内部看不出插值。

### 验证结果

代码中确实完整存在 AI 所说的每一环,顺序也一致。我特别确认到:
`vertexAttribPointer` 调用时并没有传入 Buffer 参数,说明它记录的是
“调用时刻当前绑定的那个 ARRAY_BUFFER”,而不是记住 Buffer 变量名;
任务4中 Fragment Shader 的 `in vec4 aColor` 也证实了片元阶段拿到的是
经光栅化插值后的数据。

### 修正后的结论

- 修正点1:`vertexAttribPointer` 关联的是“当前 WebGL 绑定状态”,
  这也解释了任务3换 Buffer 后为什么必须重新设置属性;
- 修正点2:Fragment Shader 是逐片元执行、接收插值结果,而不是逐顶点;
- 总体数据流确认为:
  JS 顶点数据 → Float32Array → Buffer → 顶点属性 → Vertex Shader →
  图元组装 → 光栅化(插值) → Fragment Shader → Canvas 像素。

---

## AI协作2:程序调试

### 现象

任务3第一次写成后,左侧三角形正常(橙色),右侧四边形区域空白,没有任何
图形;Console 没有报错。

### 我的初步判断

我怀疑是右侧 Buffer 没有绑定成功,或者 uniform 颜色设置成了背景色。
但没有报错信息,无法确定,于是按“只让 AI 列假设、不给完整代码”的方式
提问。

### 给AI的提示词

> 下面是一段 WebGL2 代码。第一个图形正常,第二个图形没有显示,Console
> 无报错。请不要重写完整程序,只列出最可能的3个原因,并告诉我应该通过
> 什么现象、Console 信息或代码检查逐一验证。

### AI给出的关键建议

最可能的3个原因:

1. 第二次 `drawArrays` 的顶点数量不对(例如仍写 3,配合
   `TRIANGLE_STRIP` 只够画一个退化三角形,或数量与 Buffer 数据不符);
2. 绑定第二个 Buffer 后没有重新调用 `vertexAttribPointer`,属性仍从
   第一个 Buffer 读数据,图形画到了错误位置;
3. `uColor` 在第二次绘制前被设成了与背景相同的颜色,或根本没取到
   location(可打印 location 是否为 null 验证)。

并建议逐一验证:先检查第二次 `drawArrays` 的第三个参数;再在两次绘制前
分别 `console.log(gl.getParameter(gl.ARRAY_BUFFER_BINDING))` 看绑定;
最后把第二次颜色临时改成红色排除颜色问题。

### 我实际进行了什么测试

1. 检查代码发现第二次调用被我写成了
   `gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3)`——数量是 3 而不是 4;
2. 为确认,把数量临时改为 4,刷新页面;
3. 同时核对第二个 Buffer 之后确实有重新 `vertexAttribPointer`,
   `uColor` 紫色也与背景不同。

### 测试结果

数量改为 4 后,右侧紫色四边形完整出现。其余两项检查(绑定、颜色)均
正常,可排除。

### 最终原因

`TRIANGLE_STRIP` 需要 4 个顶点才能拼出两个三角形组成四边形;只传 3 个
顶点时只会产生一个三角形,且位置落在四边形左上角附近,视觉上与预期的
右侧四边形不符,看起来像“没显示”。属于绘制顶点数量错误。

### 是否采纳AI建议及理由

采纳了 AI 的第 1 条假设,且正是根因。第 2、3 条虽不是本次原因,但我按
建议做了核验,确认它们不是问题,这种“列假设 + 指定验证方法”的方式比
直接要一份新代码更能帮我理解状态机。为完成本调试闭环,该错误是我在
推荐完成顺序中第 8 步刻意只写数量 3 制造的,随后真实排错并恢复为 4。

---

## AI协作3:顶点属性与颜色

### 我的目标

任务4中位置属性每个顶点读 2 个 float、颜色属性读 4 个 float,我想从
“GPU 具体怎样从连续的 Buffer 字节里切数据”的角度理解二者区别,并通过
对照实验验证。

### 提示词

> 在 WebGL2 中,位置属性 vPosition 每个顶点提供2个 float,而颜色属性
> vColor 每个顶点提供4个 float。请从“GPU 怎样按 vertexAttribPointer
> 的参数读取 Buffer 中连续数据”的角度解释两个属性的区别,不要只列
> 参数定义。

### AI关键回答摘要

- GPU 把绑定的 Buffer 看作一段连续字节流;`vertexAttribPointer` 的
  size 表示每顶点读取几个分量,stride=0 表示紧密排列(步长 =
  size × 每分量字节数),随后从偏移 0 开始,每“步长”切出一个顶点;
- 位置 size=2:依次读出 (x0,y0)、(x1,y1)……不足 4 分量时 z 补 0、
  w 补 1;
- 颜色 size=4:依次读出 (r,g,b,a) 四分量;
- 若把颜色 size 改成 3,读取节奏会变成每 3 个 float 一组,与原本
  4 个 float 一组的排列错位,后续顶点读到的将是“跨过”原始 RGBA
  边界的数据;未提供的第 4 分量补 1。

### 对照实验

把 [js/task4.js](js/task4.js) 中颜色属性的

```javascript
gl.vertexAttribPointer(vColor, 4, gl.FLOAT, false, 0, 0);
```

临时改为 size = 3,运行 task4.html 观察,再恢复为 4。

### 实际现象

颜色 Buffer 原始排列为

```text
[1,0,0,1, 0,1,0,1, 0,0,1,1]
 红RGBA    绿RGBA    蓝RGBA
```

改为 size=3 后,每 3 个 float 切一组:

- 顶点1读到 (1,0,0),第4分量补1 → 仍为红色;
- 顶点2读到第4~6个 float (1,0,1) → 变成品红色;
- 顶点3读到第7~9个 float (0,0,1) → 变成蓝色;

三角形仍是连续渐变,但顶点2由绿色变成品红,整体渐变配色与正确版本
明显不同。Console 无任何报错(该调用本身合法)。恢复 size=4 后立即
还原为红、绿、蓝渐变。

### 我的解释

GPU 只按 `vertexAttribPointer` 给定的“每顶点分量数 + 步长”机械地切分
连续数据,并不理解数组在 JS 端是按 4 个一组书写的。size 从 4 改成 3 后,
切分边界整体错位,再加上第 4 分量自动补 1,于是顶点 2、3 读到的数值
与我本意完全不同。AI 关于“错位读取 + w 补 1”的解释准确预测了这一现象。

### 最终结论

- 两个属性的区别本质是“每顶点读取分量数”不同:2 对应二维 xy,
  4 对应 RGBA;
- 属性与 Buffer 的对应关系在 `vertexAttribPointer` 调用时按当前绑定
  固定,size/stride 决定 GPU 的切分节奏;
- size 不匹配不会报错,只会悄悄读错数据,这提醒我:数据排列方式必须
  与 vertexAttribPointer 参数严格一致,且出现“颜色怪怪的但不报错”时
  应优先检查 size/stride。