AI 协作日志
学生 Web 实验作品平台
学号:202412211402013 · 来源:ai-log.md
# 实验一 AI协作记录
> 学号:202412211402013 姓名:顾喆祺
> 本文件记录本次实验的关键人机协作过程。每一条都包含自己的判断、测试与核验,并对应到 `task*.html` 与 `js/task*.js` 中的真实代码,未直接粘贴 AI 生成结果。
---
## AI协作1:理解数据流(对应任务1)
### 我的目标
弄清楚「一组 JavaScript 顶点数据,究竟是怎样从 Float32Array 变成屏幕上一个三角形」的完整链路,并能把每个环节对应到 `task1.html` / `js/task1.js` 里的真实代码,而不是只记住名词。
### 提示词
> 从 JavaScript 的 Float32Array 到屏幕上出现一个三角形,中间发生了哪些关键步骤?请结合 WebGL2 解释 Buffer、vertexAttribPointer、Vertex Shader、光栅化和 Fragment Shader 各自负责什么,不要直接修改我的代码。
### AI关键回答摘要
- `Float32Array` 只是 CPU 侧的普通数组,GPU 不能直接读它;必须先 `gl.createBuffer()` 建一个 Buffer,再 `gl.bufferData()` 把数组整体复制进 GPU 显存。
- `vertexAttribPointer()` 负责告诉 GPU「怎么从当前绑定的 Buffer 里切出顶点数据」:第 2 个参数表示每个顶点占几个 float,第 5、6 个参数表示步长和起始偏移。
- `gl.enableVertexAttribArray()` 才是真正「打开」这条属性通道,否则 Shader 里即使声明了 `vPosition` 也读不到数据。
- Vertex Shader 逐个顶点执行,把 `gl_Position` 输出为裁剪坐标;随后 GPU 按图元类型把顶点组装成三角形(图元组装),再进行光栅化,把三角形内部每个像素都算出来并交给 Fragment Shader。
- Fragment Shader 对每个像素执行一次,输出该像素颜色,最终写入 Canvas 对应的像素区。
### 我的判断
AI 的链路和教材第 4.3 节的初始化顺序(准备顶点数据 → 建 Buffer → bindBuffer → bufferData → getAttribLocation → vertexAttribPointer → enableVertexAttribArray → drawArrays)完全对得上,我认为可信,但「空口无凭」,需要逐行到代码里核对。
### 验证方法
打开 `task1.html` 与 `js/task1.js`,按 AI 提到的每个环节逐项找对应代码,并用浏览器 F12 的 Console 查看有无报错。
### 验证结果
逐项核对全部命中:
- `js/task1.js` 第 32–36 行:`gl.createBuffer()` → `gl.bindBuffer()` → `gl.bufferData()`,对应「建 Buffer 并上传数据」;
- 第 39–41 行:`gl.getAttribLocation()` → `gl.vertexAttribPointer(vPosition, 2, ...)` → `gl.enableVertexAttribArray()`,对应「建立属性与 Buffer 的联系」;
- `task1.html` 中 vertex-shader 声明 `in vec4 vPosition;`,fragment-shader 用 `uniform vec4 uColor` 输出 `fColor`,对应两个 Shader 的作用;
- 第 57 行 `gl.drawArrays(gl.TRIANGLES, 0, 3)` 触发整条绘制流水线。
运行后三角形正常显示,Console 无报错。
### 修正后的结论
我最初把 `gl.vertexAttribPointer(vPosition, 2, ...)` 里的 `2` 误当成「绘制 2 个顶点」。核验后修正:这个 `2` 是**每个顶点由几个 float 组成**(这里每顶点 x、y 两个分量),与「画几个顶点」无关;真正决定顶点个数的是 `gl.drawArrays` 第 3 个参数 `3`(3 个顶点),而不是 float 数量 6。这一理解帮助我在后续任务里没有再犯「把 float 数量当顶点数量」的错误。
---
## AI协作2:程序调试(对应任务3)
### 现象
`task3.html` 中左侧三角形能正常显示,但右侧四边形只画出了「半个」——缺少一块,图形不完整。
### 我的初步判断
我以为是四边形顶点坐标写错了,或者两个图形重叠被三角形遮住了。于是先检查了坐标,发现 `(0.2,0.4)(0.2,-0.4)(0.7,0.4)(0.7,-0.4)` 位于屏幕右半侧,不会与左侧三角形重叠,初步判断被排除。
### 给AI的提示词
> 下面是一段 WebGL2 代码。第一个图形(三角形)正常,第二个图形(四边形)只显示了一半。请不要重写完整程序,只列出最可能的 3 个原因,并告诉我应该通过什么现象、Console 信息或代码检查逐一验证。
### AI给出的关键建议
1. 第二段绘制用的顶点数量不对——`drawArrays` 第 3 个参数是**顶点个数**,我可能写成了 3 而不是 4,导致只组成了 1 个三角形;
2. 绘制模式选错——四边形用 `TRIANGLE_STRIP` 时,如果顶点顺序不对会得到交叉或缺失的图形;
3. 忘记在绑定第二个 Buffer 后重新调用 `vertexAttribPointer()`,导致读取的还是第一个 Buffer 的数据。
### 我实际进行的测试
1. 先在 `render()` 最前面加一行 `console.log("task3 start");`,确认 `js/task3.js` 正常加载、函数执行到了(对应实验文档 7.2 的排查顺序);
2. 检查代码,发现第二个 `drawArrays` 写的是 `gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3)`——第 3 个参数是 3,而我这个四边形有 4 个顶点;
3. 逐个核对:第二个 Buffer 已重新 bind、也已重新调用 `vertexAttribPointer` 和 `enableVertexAttribArray`,所以第 3 条原因不成立;顶点顺序是左上→左下→右上→右下,符合推荐顺序,第 2 条也不成立。
### 测试结果
Console 无报错、`task3 start` 有输出(排除加载问题);问题确实集中在 `drawArrays` 的顶点数量上——把第 3 个参数从 3 改为 4(等价于 `quad.length / 2`,因为每个顶点占 2 个 float)后,四边形补全了。
### 最终原因
`gl.drawArrays(mode, first, count)` 的第 3 个参数 `count` 是**顶点个数**,不是 float 个数。四边形有 4 个顶点、2 个三角形;我只传了 3,等于只让 `TRIANGLE_STRIP` 生成了 1 个三角形,所以图形缺了一半。
### 是否采纳AI建议及理由
采纳。AI 列出的第 1 条与我的代码核验结果完全吻合,第 2、3 条也被我主动排除,形成了一条「现象 → 判断 → 提示 → 测试 → 结论」的完整排错闭环。这也验证了实验文档第 7.8 节的提醒:最后一个参数是顶点数量,不是数组中 float 的数量。
---
## AI协作3:顶点属性与颜色(对应任务4)
### 我的目标
理解为什么位置属性 `vPosition` 每个顶点读 2 个 float、而颜色属性 `vColor` 每个顶点要读 4 个 float,以及 GPU 究竟是怎么按 `vertexAttribPointer` 的参数去 Buffer 里「切」连续数据的。
### 提示词
> 在 WebGL2 中,位置属性 vPosition 每个顶点提供 2 个 float,而颜色属性 vColor 每个顶点提供 4 个 float。请从「GPU 怎样按 vertexAttribPointer 的参数读取 Buffer 中连续数据」的角度解释两个属性的区别,不要只列参数定义。
### AI关键回答摘要
- 位置 Buffer 里每顶点存的是 `(x, y)`,所以 size = 2;颜色 Buffer 里每顶点存的是 `(R, G, B, A)`,所以 size = 4。
- GPU 是「按 stride 从 buffer 起始处、每 size 个 float 为一组」来切分的:对顶点 i,读的是 `[i×stride, i×stride + size)` 这段连续 float(stride 为 0 时按紧密排列)。
- 两个 Buffer 之所以能分别对应 `vPosition` 和 `vColor`,靠的是各自绑定 ARRAY_BUFFER 后调用 `vertexAttribPointer` 时记录下的属性索引;启用 `enableVertexAttribArray` 后,两个属性通道互相独立。
- 若 size 小于 Shader 中属性分量的个数(如 vec4 却只给 3 个),缺失的分量会被自动补默认值(w 补 1.0)。
### 对照实验
按实验文档要求,把 `js/task4.js` 中颜色属性的 `gl.vertexAttribPointer(vColor, 4, gl.FLOAT, false, 0, 0)` 里的 `4` 临时改为 `3`,保持其他参数不变,运行观察。
### 实际现象
三角形**外观没有发生明显变化**,红、绿、蓝三个顶点之间仍是平滑的连续渐变,看不出异常。
### 我的解释
我的颜色数据正好是「每个顶点前 3 个分量就是该顶点的 R、G、B,且 A 恒为 1.0」。把 size 从 4 改成 3 后,GPU 对每个顶点只读前 3 个 float,`vColor` 是 vec4,缺失的第 4 个分量 w 被自动补成 1.0(不透明)。因此无论按 size=4 还是 size=3 读取,得到的 RGB 分量完全相同、alpha 都是 1.0,视觉结果自然一致。如果颜色数据里 alpha 不是 1.0,或 RGB 分组与顶点不对齐,改小 size 就会出现明显错色。
### 最终结论
AI 的解释成立,并能完整说明观察到的现象:`vertexAttribPointer` 的 size 决定「每个顶点从 Buffer 里切几个连续 float」,vec4 属性在 size 不足时缺失分量自动补默认值。本实验数据恰好对齐,所以改 size=3 看不到变化——这恰恰验证了「GPU 按 size 从连续地址切数据」的机制,而不是推翻它。实验后我已将 `4` 恢复为正确值。
(对应代码:`js/task4.js` 第 68–84 行位置 Buffer 与颜色 Buffer 的双属性设置。)
---
## AI协作4:图元解释方式对照(对应任务5)
### 我修改了什么
将任务 2 的 4 个顶点数据原样复制到 `js/task5.js`(顶点数量、坐标、顺序、颜色均不变),仅把 `gl.drawArrays` 的绘制模式从任务 2 的 `gl.TRIANGLE_STRIP` 改为 `gl.LINE_LOOP`(第 67 行)。
### 我原先预测
`LINE_LOOP` 会用线段把 4 个顶点按顺序首尾相连成一个闭合的四边形边框,所以应该看到「四条边的轮廓」,没有填充。
### 实际结果
运行后确实只显示四边形的四条边(轮廓),内部不再有颜色填充,顶点按 `v1→v2→v3→v4→v1` 顺序连成闭合图形。
### 原因解释
同一份顶点数据只是改变了「图元解释方式」:`TRIANGLE_STRIP` 会把顶点按顺序两两组成相连的三角形并填充面片;而 `LINE_LOOP` 只是把相邻顶点连成线段并收尾闭合,不做面填充。顶点数据本身没有变,变的只是 GPU 对这批顶点的组装/光栅化规则,这正说明了「相同数据、不同 draw mode,得到不同结果」。
### 进一步对照(可加分)
在同一条件下把模式依次改为 `gl.POINTS`(只显示 4 个点)与 `gl.TRIANGLES`(每 3 个顶点组成独立三角形,4 个顶点只画出一个三角形,第 4 点不被使用),一次只改一个变量,均得到符合预期的不同结果。
---
## 验证说明
- 全部内容均对照 `task1/3/4/5` 的 `.html` 与 `js/*.js` 真实代码编写,可在对应行号处逐项核对;
- 三个关键 AI 协作均包含「自己的判断 + 验证动作」(代码核对、Console 检查、改参数做对照实验);
- 浏览器运行后各任务页面无 Console 未处理错误,图元对照实验结论与理论一致。