AI 协作日志
学生 Web 实验作品平台
学号:202412211401010 · 来源:ai-log.md
# 实验一 AI协作记录
> 请记录本人真实的AI协作过程。不要只粘贴AI生成结果,应体现自己的判断、测试和核验。
## AI协作1:理解数据流
### 我的目标
1. HTML 中定义 Vertex Shader;
2. HTML 中定义 Fragment Shader;
3. JavaScript 中创建 WebGL2 上下文;
canvas = document.getElementById("gl-canvas");
gl = canvas.getContext("webgl2");
if (!gl) {
alert("WebGL 2.0 isn't available");
return;
}
4. 使用 `initShaders()` 编译、链接并获得 Shader Program;
program = initShaders(gl, "vertex-shader", "fragment-shader");
gl.useProgram(program);
5. 创建 Buffer 并上传顶点数据;
var vertices = new Float32Array([
0.00, 0.70,
-0.65, -0.55,
0.89, -0.20
]);
var vBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
6. 建立顶点属性与 Buffer 的联系;
var vPosition = gl.getAttribLocation(program, "vPosition");
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(vPosition);
7. 调用 `gl.drawArrays()` 完成绘制。
### 提示词
从 JavaScript 的 Float32Array 到屏幕上出现一个三角形,中间发生了哪些关键步骤?
解释一下Buffer、vertexAttribPointer、Vertex Shader、光栅化和 Fragment Shader 各自负责什么,不要直接修改我的代码。
### AI关键回答摘要
AI 把整个流程拆成了几段:
1. Buffer:在 GPU 上开辟一块存储空间,用来存放顶点数据。
2. bufferData:把 JavaScript 里的 Float32Array 复制到当前绑定的 Buffer 中。
3. vertexAttribPointer:告诉 GPU 从当前 Buffer 里怎么读数据,比如每个顶点读几个 float、类型是什么、从哪个偏移开始读,把 Buffer 数据和 Shader 里的顶点属性对应起来。
4. Vertex Shader:对每个顶点执行一次,计算 gl_Position,决定顶点最终在裁剪空间里的位置。
5. 图元组装:根据 draw mode(比如 TRIANGLES)把顶点组成图元。
6. 光栅化:把图元转成片元,并对顶点属性进行插值。
7. Fragment Shader:对每个片元执行一次,决定颜色,输出到 fColor。
8. 最终片元写入 Canvas 像素。
AI 还强调:bufferData 负责“搬数据”,vertexAttribPointer 负责“说规则”,Shader 负责“算结果”,这三件事是分开的。
### 我的判断
一开始以为 vertexAttribPointer 会自动把数据上传到 GPU,后来发现它只是“描述读取规则”。真正上传数据的是 bufferData。
我还以为 Shader 里写 in vec4 vPosition 就必须在 JavaScript 里给 4 个 float,
后来发现 WebGL 会自动补默认值:z 补 0,w 补 1
### 验证方法
1. 在 task1.html 和 js/task1.js 中逐项找到 AI 提到的对应代码:
- task1.html:两个 <script id="vertex-shader"> 和 <script id="fragment-shader">;
- task1.js:getContext("webgl2")、initShaders、createBuffer、bindBuffer、bufferData、getAttribLocation、vertexAttribPointer、enableVertexAttribArray、uniform4f、drawArrays。
2. 修改一个顶点坐标:把右下顶点从 (0.65, -0.55) 改成 (0.89, -0.20),刷新页面观察三角形形状;
3. 修改 uniform4f 的颜色:从红色改成绿色 (0.2, 0.8, 0.3, 1.0),观察颜色是否变化。
### 验证结果
- 修改顶点坐标后,三角形右下角明显往右上移动,形状变了,说明 Buffer 里的数据确实影响绘制;
- 修改 uniform4f 后,三角形从红色变成绿色,说明 Fragment Shader 用的是 uColor;
- 在 task1.html 里找到了 gl_Position 和 fColor,分别对应 Vertex Shader 和 Fragment Shader 的输出;
- 在 task1.js 里找到了 bufferData、vertexAttribPointer、drawArrays 等代码,对应 AI 说的各个步骤。
### 修正后的结论
完整数据流是:
JavaScript Float32Array
→ bufferData 上传到 GPU Buffer
→ vertexAttribPointer 描述读取规则
→ Vertex Shader 计算 gl_Position
→ 图元组装
→ 光栅化并插值
→ Fragment Shader 决定颜色
→ 写入 Canvas 像素
问题1:
1. `Float32Array` 中连续两个数为什么可以表示一个二维顶点?
第二个参数是2
2. Shader 中声明的是:
```glsl
in vec4 vPosition;
```
而 JavaScript 中:
```javascript
gl.vertexAttribPointer(
vPosition,
2,
...
);
```
为什么仍然可以正常绘制?
WebGL 会自动补齐缺少的分量,使用默认值:
x、y 用 JavaScript 提供的值
z 补默认值 0
w 补默认值 1
3. `gl.drawArrays(gl.TRIANGLES, 0, 3)` 中最后的 `3` 表示什么?
表示使用三个顶点
4. 修改 JavaScript 中的顶点数据后,为什么要重新执行 `gl.bufferData()` 才能改变 GPU 中的数据?
因为 bufferData 才是把 JavaScript 数组复制到 GPU Buffer 的动作
## AI协作2:程序调试
### 现象
打开 task3.html 后,左侧三角形正常显示(蓝色),右侧四边形不显示。
Console 没有红色报错
### 我的初步判断
可能是四边形 Buffer 没绑定成功,或者顶点属性没有正确指向四边形 Buffer。
因为三角形能显示,说明 Shader、上下文、三角形自己的 Buffer 都没问题,
所以问题应该出在四边形绘制这一段。
### 给AI的提示词
第一个图形(三角形)正常,第二个图形(四边形)没有显示。
请不要重写完整程序,只列出最可能的3个原因,并告诉我应该通过什么现象、Console 信息或代码检查逐一验证。
### AI给出的关键建议
1. 绑定新 Buffer 后没有重新调用 vertexAttribPointer,导致顶点属性还指向旧 Buffer;
2. 绘制顶点数量写错,比如四边形写成了 3;
3. uniform 位置获取错误,导致颜色没设上,或者被覆盖。
AI 建议我:
- 检查绑定四边形 Buffer 后是否重新调用了 vertexAttribPointer;
- 在 drawArrays 前打印 vPosition 和 uColor 的值,确认不是 null;
- 检查 drawArrays 的最后一个参数是不是 4。
### 我实际进行的测试
1. 在四边形绘制前加 console.log(vPosition) 和 console.log(uColor),确认它们不是 null;
2. 对比三角形绘制代码和四边形绘制代码,发现三角形有 vertexAttribPointer,四边形没有;
3. 把 vertexAttribPointer 加回四边形绘制代码,刷新页面。
### 测试结果
加上 vertexAttribPointer 后,四边形正常显示,颜色是橙色。
三角形不受影响,仍然是蓝色。
### 最终原因
绑定新 Buffer 后没有重新调用 vertexAttribPointer,
顶点属性仍然指向三角形 Buffer 的读取规则,
导致四边形绘制时 GPU 读取的数据不对,图形不显示。
### 是否采纳AI建议及理由
采纳。AI 列出的第一个原因正好命中问题。
我也通过实际对比代码、加回 vertexAttribPointer 后重新运行,验证了这个结论
问题2:
1. 相同顶点数据为什么会得到不同图形?
因为 gl.drawArrays() 的第一个参数是 draw mode,它决定 GPU 如何解释这些顶点
2. `TRIANGLE_STRIP` 中顶点顺序为什么重要?
因为 TRIANGLE_STRIP 是按顶点顺序滑动组装的
3. 4个顶点通过 `TRIANGLE_STRIP` 实际组成了几个三角形?
2个
---
## AI协作3:顶点属性与颜色
### 我的目标
理解 vPosition 每个顶点读 2 个 float、vColor 每个顶点读 4 个 float 的区别,
以及 GPU 怎样按 vertexAttribPointer 的参数从 Buffer 中连续读取数据。
### 提示词
在 WebGL2 中,位置属性 vPosition 每个顶点提供 2 个 float,
而颜色属性 vColor 每个顶点提供 4 个 float。
请从“GPU 怎样按 vertexAttribPointer 的参数读取 Buffer 中连续数据”的角度解释两个属性的区别,
不要只列参数定义。
### AI关键回答摘要
AI 解释:
- vertexAttribPointer 的第二个参数是“每个顶点读几个分量”;
- 位置属性写 2,GPU 就按每 2 个 float 一组读,第 1 个是 x,第 2 个是 y;
- 颜色属性写 4,GPU 就按每 4 个 float 一组读,依次是 R、G、B、A;
- 读取时按 stride 和 offset 跳转,如果 stride 是 0,就表示紧密排列,GPU 会按“分量数 × 类型大小”自动计算下一个顶点的起始位置;
- 所以 vPosition 和 vColor 是两个独立的属性,各自绑定自己的 Buffer,各自有自己的读取规则。
### 对照实验
把颜色 Buffer 的:
gl.vertexAttribPointer(vColor, 4, gl.FLOAT, false, 0, 0);
中的 4 临时改成 3:
gl.vertexAttribPointer(vColor, 3, gl.FLOAT, false, 0, 0);
### 实际现象
颜色明显错乱,不再是红、绿、蓝三个顶点对应的连续渐变。
三角形内部的颜色分布变得不正常,某些区域颜色偏移或异常。
### 我的解释
因为颜色 Buffer 里每个顶点实际有 4 个 float(R、G、B、A),
但 vertexAttribPointer 告诉 GPU 每个顶点只读 3 个 float,
所以 GPU 读取的起点就错位了:
- 第 1 个顶点读 R1、G1、B1;
- 第 2 个顶点从第 4 个 float 开始读,读到的是 A1、R2、G2;
- 第 3 个顶点继续错位。
导致 vColor 拿到的颜色数据不是原本的红、绿、蓝,所以颜色错乱。
### 最终结论
每个顶点的颜色必须读 4 个 float(RGBA),
所以 vertexAttribPointer 的第二个参数必须是 4,不能是 3。
恢复成 4 后,颜色恢复正常,说明 AI 从“按参数读取连续数据”角度的解释是正确的。
问题3:
1. 为什么改变 uniform 后不需要重新编译 Shader?
因为 uniform 是 Shader 程序的外部输入,不是 Shader 源码的一部分。每次绘制前用 gl.uniform4f() 设置新值就行,不用改 Shader 源码,也不用重新编译和链接
2. 如果只设置一次 uColor,随后绘制两个对象,会发生什么?
两个对象会使用同一个颜色,因为它们共享同一个 uniform 值,后面绘制时没有再次修改它。
3. 为什么绑定新 Buffer 后需要再次正确设置顶点属性读取方式?
因为 vertexAttribPointer 记录的是“当前绑定的 Buffer 的读取规则”。换 Buffer 后,如果不重新调用 vertexAttribPointer,顶点属性可能仍然指向旧 Buffer,或者读取规则和旧 Buffer 不匹配,导致图形错误或不显示。
4. “当前 WebGL 状态会影响后续绘制”在本任务中体现在哪里?
当前绑定的 Buffer:绑定新 Buffer 后,后续 vertexAttribPointer 和绘制都指向新 Buffer;
当前 uniform 值:uColor 改了以后,后面绘制就用新颜色;
当前 draw mode:三角形用 TRIANGLES,四边形用 TRIANGLE_STRIP,各自独立。
问题4:
1. 为什么位置 Buffer 每个顶点读取 2 个 float,而颜色 Buffer 每个顶点读取 4 个 float?
因为位置是二维的,只需要 x、y 两个分量;颜色是 RGBA 四个分量,需要 R、G、B、A 四个 float。vertexAttribPointer 的第二个参数就是告诉 GPU 每个顶点读几个 float。
2. 两个 Buffer 如何分别对应到 vPosition 和 vColor?
分别通过两次 vertexAttribPointer:
绑定位置 Buffer 后,调用 gl.vertexAttribPointer(vPosition, 2, ...),把位置 Buffer 和 vPosition 关联;
绑定颜色 Buffer 后,调用 gl.vertexAttribPointer(vColor, 4, ...),把颜色 Buffer 和 vColor 关联。
3. 三角形内部为什么出现连续渐变色,而不是只有红、绿、蓝三个区域?
因为光栅化阶段会对顶点属性进行插值。三角形内部每个像素的颜色,是根据它到三个顶点的距离,把三个顶点的颜色按权重混合得到的,所以是连续渐变。
4. 顶点颜色插值主要发生在哪个阶段?Fragment Shader 得到的是顶点原始颜色还是插值后的颜色?
插值发生在光栅化阶段。Fragment Shader 得到的是插值后的颜色,不是顶点原始颜色。