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。