AI 协作日志

学生 Web 实验作品平台

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

# 实验一 AI协作记录

> 学号:202412211401032
> 记录本人真实的 AI 协作过程,包含自己的判断、对照实验与核验结果。

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

### 我的目标

在动手修改任务1之前,先弄清楚一组 JavaScript 顶点数据是怎样最终变成屏幕上的三角形的,并要求 AI 只解释、不改代码。

### 提示词

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

### AI关键回答摘要

- `Float32Array` 只在 CPU 内存中;`gl.bufferData()` 才把数据真正复制到 GPU 的 Buffer 对象里。
- `vertexAttribPointer()` 不搬运数据,它告诉 GPU“从当前绑定的 ARRAY_BUFFER 中、按几个 float 一组、步距多少、偏移多少”去取数,并把这套读取规则登记到指定顶点属性上。
- Vertex Shader 逐顶点执行,输出 `gl_Position`;图元组装把顶点连成三角形;光栅化把三角形拆成片元;Fragment Shader 逐片元执行给出颜色。

### 我的判断

AI 的说法大体可信,但“vertexAttribPointer 只是登记读取规则、数据归属在调用时绑定的 Buffer”这一点我之前理解模糊,我原以为“绑定到哪个 Buffer 决定一切”。需要对照代码逐项核验,而不是直接接受。

### 验证方法

在 task1.html 和 js/task1.js 中逐项找对应代码并运行观察:

| AI 所说环节 | 代码位置 |
|---|---|
| 顶点数据(CPU) | task1.js 中 `var vertices = new Float32Array([...])` |
| 上传到 GPU Buffer | `gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)` |
| 登记读取规则 | `gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0)` |
| Vertex Shader | task1.html 中 `in vec4 vPosition; gl_Position = vPosition;` |
| Fragment Shader | task1.html 中 `uniform vec4 uColor; fColor = uColor;` |
| 绘制 | `gl.drawArrays(gl.TRIANGLES, 0, 3)` |

### 验证结果

页面正常显示紫色不等边三角形,Console 无错误。修改顶点后必须重新执行 `bufferData` 才看到形变,证明确实存在“CPU 数据 → GPU 副本”的复制过程。

### 修正后的结论

- **修正点**:我最初以为 bindBuffer 之后属性就一直跟着“当前绑定”走。核验任务4双 Buffer 后明确:`vertexAttribPointer` 调用时会把当时绑定的 Buffer“记录”在该属性上,之后再 bind 别的 Buffer 不影响已登记好的属性。
- 任务1思考题回答:
  1. `vertexAttribPointer` 指定每 2 个 float 为一组,GPU 按 (x, y) 切分连续内存,故连续两个数表示一个二维顶点。
  2. Shader 声明 `vec4` 而只提供 2 个分量时,缺失的 z、w 自动补为 0、1,即 (x, y, 0, 1),所以绘制正常。
  3. `drawArrays` 最后的 `3` 是**顶点数量**(3个顶点),不是数组中 float 的个数。
  4. `bufferData` 是把数据从 CPU 复制到 GPU;只改 JS 数组,GPU 中的副本不会自动更新,必须重新上传。

---

## AI协作2:程序调试

### 现象

任务3完成后,左侧三角形正常,右侧四边形只显示了一半(一个三角形),且右半部分缺失。

### 我的初步判断

怀疑是四边形 Buffer 数据没上传全,或顶点属性读取方式没重新设置。

### 给AI的提示词

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

### AI给出的关键建议

最可能的3个原因:
1. `drawArrays` 的顶点数量参数错误(例如四边形仍写 3);
2. 绑定新 Buffer 后没有重新调用 `vertexAttribPointer`,属性仍指向三角形 Buffer;
3. `vertices` 数组本身少写了顶点。

并建议:Console 里打印 count;把鼠标/坐标与四个预期角点对照;单独检查第二次 drawArrays 的最后一个参数。

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

1. 检查 `quad` Float32Array:8 个 float,4 个顶点齐全,排除原因3。
2. 核对第二次绘制前的 `bindBuffer/vertexAttribPointer`:均已正确执行,排除原因2。
3. 定位到第二次绘制被我误写成 `gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3)`。
4. 为验证该假设,在页面 Console 中直接执行:

```javascript
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3);   // 复现:只有半个四边形
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);   // 对照:完整四边形
```

(render 执行后当前绑定的 ARRAY_BUFFER 正是四边形 Buffer,vPosition 也指向它,故可直接重绘。)

### 测试结果

count = 3 时稳定复现“半个四边形”;改回 4 后四边形完整,假设被证实。

### 最终原因

第二次 `drawArrays` 的顶点数量误写为 3,TRIANGLE_STRIP 只用前 3 个顶点生成了一个三角形。

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

采纳。AI 没有代写代码,而是给出可逐一证伪的排查清单;我通过“检查数组→检查属性→检查 count”的顺序和 Console 对照实验定位问题,其中 count 检查最快验证,与其建议一致。

任务3其余思考题结论:

- uniform 是 Program 运行期可改的状态值,不参与编译,改 uniform 只需 `gl.uniform4f`,无需重新编译 Shader。
- 若只设置一次 `uColor`,两个对象会是同一种颜色(uniform 值一直保留到下次修改)。
- 绑定新 Buffer 后必须重新 `vertexAttribPointer`,否则属性仍按旧规则从旧 Buffer 读数据。
- “当前 WebGL 状态影响后续绘制”体现在:当前绑定的 ARRAY_BUFFER、uniform 当前值、图元模式、顶点数量都决定下一次 drawArrays 的结果,所以第二次绘制前要逐一更新状态。

---

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

### 我的目标

理解为什么 vPosition 每顶点读 2 个 float、vColor 每顶点读 4 个 float,并通过对照实验验证。

### 提示词

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

### AI关键回答摘要

GPU 把属性对应的 Buffer 看作连续字节流:size 决定每几个 float 打包成一个顶点的该属性,stride=0 表示紧密排列。因此位置 Buffer 按 [x,y][x,y]… 切分,颜色 Buffer 按 [r,g,b,a][r,g,b,a]… 切分;两条流按下标在同一次绘制中配对成同一个顶点。若颜色 size 写成 3,则改按 [r,g,b][r,g,b]… 从同一个颜色数组重新切分,顶点间数据会“错位”,第 4 分量取默认值 1。

### 对照实验

页面正常加载后,在 Console 中执行(颜色数组为 [1,0,0,1, 0,1,0,1, 0,0,1,1]):

```javascript
var loc = gl.getAttribLocation(program, "vColor");
gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0);  // 4 临时改为 3
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 3);
```

### 实际现象

三角形没有报错,但颜色变成“红 → 品红 → 蓝”的渐变,而不是正确的“红 → 绿 → 蓝”。恢复 size = 4 后颜色恢复正常。

### 我的解释

size=3 时 GPU 按 3 个 float 一组重新切分颜色流:第1顶点读到 (1,0,0) 红;第2顶点读到的是数组第 4~6 个数 (1,0,1) 品红;第3顶点读到 (0,0,1) 蓝;alpha 缺省为 1。错位恰好解释了绿色顶点变品红的现象,AI 的“按 size 重新切分连续数据”的解释能够说明观察结果。

### 最终结论

- 位置是二维坐标,所以每顶点读 2 个 float;颜色是 RGBA,所以读 4 个 float。
- 两个 Buffer 分别在各自的 `vertexAttribPointer` 中登记给 `vPosition` 与 `vColor`,绘制时按顶点下标配对。
- 三角形内部为连续渐变而非三块纯色,是因为光栅化阶段对顶点属性做了重心插值;Fragment Shader 收到的 `aColor` 是**插值后**的颜色,不是顶点原始颜色,插值发生在光栅化阶段。

---

## 附:任务2对照实验记录(只改图元,顶点数据不变)

| draw mode | 实际结果 |
|---|---|
| gl.TRIANGLE_STRIP | 完整填充四边形(2个三角形) |
| gl.POINTS | 只剩4个孤立的点(顶点位置) |
| gl.LINE_STRIP | 左上→左下→右上→右下 的3条线段折线,出现一条对角线、不闭合、不填充 |
| gl.TRIANGLES | 4个顶点中只有前3个组成1个填充三角形,第4个顶点被忽略 |

结论:相同顶点数据,图元类型决定 GPU 如何把顶点“组装”成图元,所以结果不同;TRIANGLE_STRIP 中顶点顺序决定每相邻三个顶点如何生成三角形,顺序错乱会得到扭曲或错误的图形;4个顶点在 TRIANGLE_STRIP 下实际生成 4−2 = 2 个三角形。

---

## 附:任务5记录

- 我修改了什么:将任务2的 4 个顶点原样复制,只把 mode 由 `gl.TRIANGLE_STRIP` 改为 `gl.LINE_STRIP`(颜色也保持任务2的绿色)。
- 我原先预测:会看到四边形的线框轮廓。
- 实际结果:没有填充,也不是完整线框,只有 左边、对角线、右边 三条线段,首尾不闭合。
- 原因解释:LINE_STRIP 严格按顶点提交顺序连接相邻顶点;为三角形条带设计的“之”字形顺序在折线解释下产生对角线,且 LINE_STRIP 不自动连接首尾。改用 `gl.LINE_LOOP` 可得到闭合轮廓(但仍不填充)。