AI 协作日志
学生 Web 实验作品平台
学号:202412211402016 · 来源:ai-log.md
# 实验一 AI协作记录
> 请记录本人真实的AI协作过程。不要只粘贴AI生成结果,应体现自己的判断、测试和核验。
## AI协作1:理解数据流
### 我的目标
理解实验一的整体操作流程,并弄清楚 JavaScript 中定义的顶点数据是如何经过 WebGL2 最终显示到 Canvas 上的。
### 提示词
学习一下这些内容,告诉我从头的操作,代码可以使用vscode
### AI关键回答摘要
AI首先介绍了使用 VS Code 完成实验的基本流程,包括解压实验文件、使用 VS Code 打开实验目录、通过 Live Server 运行 `index.html`,然后按照 `task1` 到 `task5` 的顺序完成实验。
对于 WebGL 的数据流,AI解释了顶点数据首先使用 `Float32Array` 保存在 JavaScript 中,然后通过 `gl.bufferData()` 上传到 GPU Buffer。之后通过 `gl.vertexAttribPointer()` 规定 GPU 如何读取 Buffer 中的数据,并将数据传递给 Vertex Shader。顶点经过图元组装和光栅化后,再由 Fragment Shader 决定最终显示的颜色。
### 我的判断
开始时我主要把 Buffer 理解成普通的 JavaScript 数组,没有注意到 JavaScript 中的数据和 GPU 中的数据并不是同一部分。
根据 AI 的解释,我认为 `gl.bufferData()` 是将 CPU 端的数据上传到 GPU,而 `gl.vertexAttribPointer()` 是建立 GPU Buffer 与 Shader 顶点属性之间联系的重要步骤。
### 验证方法
我在 `task1.js` 中按照程序执行顺序查看:
```javascript
gl.createBuffer();
gl.bindBuffer();
gl.bufferData();
gl.getAttribLocation();
gl.vertexAttribPointer();
gl.enableVertexAttribArray();
gl.drawArrays();
```
同时查看 `task1.html` 中 Vertex Shader 的:
```glsl
in vec4 vPosition;
```
并与 JavaScript 中获取 `vPosition` 的代码进行对应。
之后修改三角形的一个顶点坐标和颜色并重新运行程序。
### 验证结果
修改顶点坐标后,三角形的形状发生了变化;修改 `uColor` 后,三角形的颜色也发生变化。
程序中的代码顺序与 AI 对数据流的解释一致,说明顶点数据确实需要先进入 GPU Buffer,再通过顶点属性传递给 Shader。
### 修正后的结论
WebGL2 中,Shader 不能直接读取 JavaScript 中的 `Float32Array`。顶点数据需要先上传到 GPU Buffer,再使用 `vertexAttribPointer()` 指定数据的读取方式。
整个过程可以概括为:
```text
JavaScript顶点数据
→ Float32Array
→ GPU Buffer
→ 顶点属性
→ Vertex Shader
→ 图元组装
→ 光栅化
→ Fragment Shader
→ Canvas像素
```
---
## AI协作2:程序调试
### 现象
完成任务3后,左侧三角形和右侧四边形都能够正常显示。
为了进行调试测试,我将四边形原来的:
```javascript
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
```
临时修改为:
```javascript
gl.drawArrays(gl.TRIANGLES, 0, 4);
```
重新运行后,左侧三角形仍然正常,但是右侧四边形不能完整显示,只显示出了一个三角形区域。
### 我的初步判断
因为我没有修改四边形的4个顶点坐标,所以我认为问题应该不是顶点数据导致的。
我怀疑是修改了 `gl.drawArrays()` 中的图元类型,使 GPU 对相同顶点采用了不同的组合方式。
### 给AI的提示词
任务3中第一个三角形能够正常显示,但是第二个四边形显示不完整。四边形的顶点数据没有修改,只修改了 `gl.drawArrays()` 中的 draw mode。请不要重新写完整程序,告诉我可能的原因以及应该如何验证。
### AI给出的关键建议
AI建议依次检查:
1. 四边形的 draw mode 是否仍然为 `gl.TRIANGLE_STRIP`;
2. `gl.drawArrays()` 中的顶点数量是否正确;
3. 绘制四边形之前是否正确绑定了对应 Buffer;
4. 更换 Buffer 后是否重新设置了 `vertexAttribPointer()`。
AI指出 `gl.TRIANGLES` 和 `gl.TRIANGLE_STRIP` 对同一组顶点的组织方式不同,因此即使顶点坐标完全一样,最终得到的图形也可能不同。
### 我实际进行的测试
我首先确认四边形仍然包含4个顶点,并检查绘制前的 Buffer 绑定和 `vertexAttribPointer()`,这些代码均没有改变。
随后只把:
```javascript
gl.TRIANGLES
```
恢复为:
```javascript
gl.TRIANGLE_STRIP
```
其他代码保持不变,再次运行程序。
### 测试结果
恢复 `gl.TRIANGLE_STRIP` 后,右侧四边形重新完整显示,左侧三角形也保持正常。
### 最终原因
`gl.TRIANGLES` 每3个顶点组成一个独立的三角形。
四边形只有4个顶点,因此前三个顶点可以构成一个三角形,但是剩余的一个顶点无法单独构成第二个三角形。
`gl.TRIANGLE_STRIP` 可以利用4个连续顶点组成两个相邻三角形,因此能够绘制完整四边形。
### 是否采纳AI建议及理由
采纳了 AI 关于检查 draw mode 的建议。
我通过只改变一个变量进行对照测试,发现恢复 `gl.TRIANGLE_STRIP` 后图形立即恢复正常,因此能够确认问题确实来自图元类型,而不是顶点坐标或 Buffer。
这次调试也让我理解了,相同的顶点数据使用不同的 draw mode 会产生不同的绘制结果。
---
## AI协作3:顶点属性与颜色
### 我的目标
理解任务4中位置属性 `vPosition` 和颜色属性 `vColor` 为什么需要使用不同的 `vertexAttribPointer()` 参数,以及三角形内部为什么会出现连续的渐变颜色。
### 提示词
在 WebGL2 中,位置属性 `vPosition` 每个顶点提供2个 float,而颜色属性 `vColor` 每个顶点提供4个 float。请从 GPU 怎样通过 `vertexAttribPointer()` 读取 Buffer 中连续数据的角度解释它们的区别。
### AI关键回答摘要
AI解释了 `vertexAttribPointer()` 的第二个参数表示每个顶点属性包含多少个数据分量。
位置数据的形式为:
```text
x, y
```
因此每个顶点读取2个 `float`。
颜色数据的形式为:
```text
R, G, B, A
```
因此每个顶点读取4个 `float`。
位置数据和颜色数据分别存放在不同的 Buffer 中,通过 `vPosition` 和 `vColor` 两个不同的 Shader 属性进行对应。
三角形内部的渐变颜色则是在光栅化过程中,根据三个顶点的颜色进行插值得到的。
### 对照实验
正确的颜色属性代码为:
```javascript
gl.vertexAttribPointer(
vColor,
4,
gl.FLOAT,
false,
0,
0
);
```
按照实验要求,我将其中的:
```javascript
4
```
临时修改为:
```javascript
3
```
运行程序并观察颜色变化,之后再恢复为正确的 `4`。
### 实际现象
当参数为 `4` 时,三个顶点分别显示红、绿、蓝三种颜色,并且三角形内部形成连续的渐变。
将参数修改为 `3` 后,颜色显示发生异常,三个顶点的颜色与原来设置的红、绿、蓝不再正确对应。
恢复为 `4` 后,颜色显示重新正常。
### 我的解释
颜色数组原来的存储方式是:
```text
R G B A | R G B A | R G B A
```
每4个 `float` 对应一个顶点。
当 `vertexAttribPointer()` 的参数为 `4` 时,GPU能够按照正确的数据边界读取每个顶点颜色。
如果修改为 `3`,GPU会按照:
```text
R G B | A R G | B A R | ...
```
的方式重新划分数据,因此原来的颜色数据被错误分组,最终导致颜色显示异常。
另外,三角形内部并没有单独定义大量颜色,而是 GPU 在光栅化过程中根据三个顶点的颜色进行插值,因此会看到连续的渐变效果。
### 最终结论
`vertexAttribPointer()` 中设置的分量数量必须与 Buffer 中实际的数据组织方式一致。
位置属性:
```text
x, y
```
所以每个顶点读取2个 `float`。
颜色属性:
```text
R, G, B, A
```
所以每个顶点读取4个 `float`。
不同顶点的颜色经过光栅化阶段插值后,再传递给 Fragment Shader,因此最终能够在三角形内部形成连续的渐变颜色。