AI 协作日志

学生 Web 实验作品平台

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

# 实验一 AI协作记录

> 请记录本人真实的AI协作过程。不要只粘贴AI生成结果,应体现自己的判断、测试和核验。

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

### 我的目标
弄清从 JavaScript 的 Float32Array 顶点数据,到屏幕上出现一个三角形的完整数据流,重点理解 Buffer、vertexAttribPointer、Vertex Shader、光栅化、Fragment Shader 各自负责什么,并能在 task1.html 和 js/task1.js 里逐项找到对应代码。
### 提示词
从 JavaScript 的 Float32Array 到屏幕上出现一个三角形,中间发生了哪些关键步骤?请结合 WebGL2 解释 Buffer、vertexAttribPointer、Vertex Shader、光栅化和 Fragment Shader 各自负责什么,不要直接修改我的代码。
### AI关键回答摘要
AI 给出的关键步骤大致如下:
1、JavaScript 侧组织顶点数据:用 Float32Array 在 CPU 内存中存放顶点坐标。
2、创建并绑定 Buffer:gl.createBuffer() 申请 GPU Buffer,gl.bindBuffer() 把它设为当前 ARRAY_BUFFER。
3、上传数据到 GPU:gl.bufferData() 把 CPU 端数据拷贝到 GPU 显存。
4、建立顶点属性与 Buffer 的联系:gl.vertexAttribPointer() 描述“GPU 按什么规则从 Buffer 中读数据”,gl.enableVertexAttribArray() 真正启用该属性。
5、Vertex Shader 逐顶点执行:读取 in vPosition,计算并写入 gl_Position。
6、图元组装 + 光栅化:gl.drawArrays(gl.TRIANGLES, 0, 3) 触发图元组装和光栅化,把三角形切成像素,并对顶点属性做插值。
7、Fragment Shader 逐像素执行:计算每个像素的颜色,写入自定义输出变量 fColor。
8、写入 Canvas 像素:最终结果出现在 Canvas 上。
### 我的判断
AI 的描述与课程中“JavaScript 顶点数据 → TypedArray → GPU Buffer → 顶点属性 → Vertex Shader → 图元组装 → 光栅化 → Fragment Shader → Canvas 像素”的数据流一致。
但仅凭一段解释还不能完全确认,因为其中有些说法比较笼统,例如:
“建立联系”具体对应哪几行代码?
光栅化没有显式代码,它到底在什么时机发生?
Vertex Shader 和 Fragment Shader 分别执行多少次?
这些都需要逐条到代码里核验。
### 验证方法
在 task1.html 和 js/task1.js 中逐项查找 AI 所说步骤的对应代码,形成一一对应
核验方式:
1、把 js/task1.js 从上到下逐行读一遍,确认每个关键调用都在;
2、对照 task1.html 中的 Vertex Shader 和 Fragment Shader,确认 AI 说的“逐顶点/逐像素”确实对应两个 Shader;
3、故意把 gl.drawArrays(gl.TRIANGLES, 0, 3) 的 3 改成 1,看画面是否消失;改回 3 后恢复,从而确认光栅化确实由 drawArrays 触发。
### 验证结果
表中的每一项都能在 task1.html 或 js/task1.js 中找到对应代码;
把 drawArrays 的最后一个参数由 3 改为 1 后,Canvas 上没有三角形;
改回 3 后三角形重新出现;
说明“绘制由 drawArrays 触发、并把顶点组合成三角形”这一说法与代码行为一致;
AI 描述的步骤顺序与代码执行顺序一致。
### 修正后的结论
我原先理解不清的是 gl.vertexAttribPointer 的作用,一度以为它只是“告诉 GPU 用哪个变量”,核验代码后修正为:
gl.vertexAttribPointer 本质上是在描述 Buffer 中顶点数据的内存布局,即“GPU 应该如何从连续内存中切分出一个个顶点属性”。它同时指定了:
属性位置(vPosition 的 location);
每个顶点读几个分量(这里的 2);
分量类型(gl.FLOAT);
是否归一化(false);
步长(0 表示紧密排列);
起始偏移(0)。
enableVertexAttribArray 才是“真正启用”该属性的调用。
同时进一步确认:
gl.bufferData 是把 CPU 端数据拷贝到 GPU 显存的动作,JS 端数组后续再改不会自动同步到 GPU;
光栅化没有显式 JavaScript 调用,是 gl.drawArrays 触发的内部阶段;
Vertex Shader 每个顶点执行一次,Fragment Shader 每个像素执行一次。
---

## AI协作2:程序调试

### 现象
在完成 js/task3.js 后,左侧红色三角形显示正常,但右侧四边形没有完整显示——只画出了一个小三角形,看起来像“半个四边形”,颜色还是红色,和三角形同色。
### 我的初步判断
我怀疑问题出在四边形那一段绘制代码里,可能是:
gl.drawArrays() 的顶点数量参数写错了;
或者第二次 gl.uniform4f() 忘了写,导致颜色没变;
也可能是 TRIANGLE_STRIP 的顶点顺序不对,导致拼不出完整四边形
### 给AI的提示词
下面是一段 WebGL2 代码。第一个图形(三角形)正常,第二个图形(四边形)只画出了半个,而且颜色和第一个图形相同。请不要重写完整程序,只列出最可能的3个原因,并告诉我应该通过什么现象、Console 信息或代码检查逐一验证。
### AI给出的关键建议
AI 给出 3 个最可能的原因:

gl.drawArrays() 最后一个参数写错:四边形有 4 个顶点,如果写成 3,只会画出前 3 个顶点组成的 1 个三角形,表现为“半个四边形”。

第二次 gl.uniform4f() 没写或写在了 drawArrays 之后:uniform 是状态,不重新设置就会沿用上一次的颜色。

第二次 gl.vertexAttribPointer() 遗漏或参数错:换了 Buffer 后没重设读取方式,会按旧 Buffer 的布局读取,导致图形错乱。

验证方式:

检查第二段 gl.drawArrays 的第三个参数是否是 4;

检查第二次 gl.uniform4f 是否位于四边形 drawArrays 之前;

检查第二段 gl.bindBuffer 之后是否紧接着调用了 gl.vertexAttribPointer。
### 我实际进行的测试
按 AI 的建议逐条核验,我先做了第一个最明显的测试:
1、把四边形那一句:
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3);
临时改成:
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
2、同时确认四边形 drawArrays 前面有:
gl.uniform4f(uColor, 0.20, 0.40, 0.85, 1.0);
3、再刷新页面观察结果
### 测试结果
把 3 改成 4 后,四边形完整显示;
颜色也变成了蓝色(因为 uniform4f 已正确写在了四边形绘制之前);
Console 无红色报错。
### 最终原因
根因是第二个 gl.drawArrays() 的顶点数量参数写成了 3,而四边形有 4 个顶点,所以只画出前三个顶点组成的一个三角形,表现为“只画了半个”。颜色问题其实是核对过程中一并检查后确认早已正确,真正需要修改的只有顶点数量。
### 是否采纳AI建议及理由
采纳。理由:
AI 给出的 3 条原因中,第 1 条“顶点数量写错”直接命中了我的实际错误;
它没有直接重写我的代码,而是给出了可验证的排查方向;
我按照它建议的顺序逐条检查,并通过“改 3 为 4 → 刷新 → 观察”的对照实验完成了验证;
最终我亲手确认了错误位置并修正,符合实验要求的“运行 → 观察 → 判断 → 验证”闭环。


---

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

### 我的目标
理解 gl.vertexAttribPointer 的参数究竟怎样决定 GPU 从 Buffer 中读取数据的方式,特别是为什么位置属性每顶点读 2 个 float、颜色属性每顶点读 4 个 float,并通过一个对照实验验证自己对这两个属性区别的理解。
### 提示词
在 WebGL2 中,位置属性 vPosition 每个顶点提供2个 float,而颜色属性 vColor 每个顶点提供4个 float。请从“GPU怎样按 vertexAttribPointer 的参数读取 Buffer 中连续数据”的角度解释两个属性的区别,不要只列参数定义。
### AI关键回答摘要
AI 的回答可以概括为:
gl.vertexAttribPointer(location, size, type, normalized, stride, offset) 中的关键参数是:
size:每个顶点从 Buffer 中读几个分量;
type:每个分量的类型(这里是 gl.FLOAT,4 字节);
stride:两个相邻顶点之间的字节间隔(0 表示紧密排列);
offset:从 Buffer 起始到第一个顶点数据的字节偏移。
当 stride = 0 时,GPU 会按 size × sizeof(type) 自动算出步长,从而把连续内存切成一个个顶点属性;
对位置来说,size = 2,每顶点占 8 字节,所以 Buffer 被切成 (x, y);
对颜色来说,size = 4,每顶点占 16 字节,所以 Buffer 被切成 (r, g, b, a);
两个属性虽然都来自不同 Buffer,但各自按自己的 size 独立解析,互相不影响;
Shader 中 in vec4 vColor; 需要 4 个分量,所以 size 必须是 4;如果只写 3,就会与 Shader 期望的 4 个分量不匹配。
### 对照实验
在 js/task4.js 中,把颜色 Buffer 的属性设置:
gl.vertexAttribPointer(vColor, 4, gl.FLOAT, false, 0, 0);、
中的 4 临时改为 3,即:
gl.vertexAttribPointer(vColor, 3, gl.FLOAT, false, 0, 0);
其它代码不变,刷新页面观察,然后再改回 4。
### 实际现象
改成 3 后,三角形颜色显示不正常:
颜色发生错位,出现明显的异常色块;
三角形内部不再是平滑的红→绿→蓝渐变;
Console 中可能不会报错,但画面明显错误。
改回 4 后,恢复正常的红、绿、蓝渐变。
### 我的解释
size = 3 时,GPU 认为每个顶点只占 12 字节(3 个 float),但实际上 Buffer 中每个顶点是 16 字节(4 个 float,含 A);
于是 GPU 会把顶点 1 的 B 当成顶点 2 的 R、顶点 1 的 A 当成顶点 2 的 G,数据整体错位;
顶点 3 的读取也会越界,取到不属于它的数据;
最终结果是颜色错乱,而不是简单的“只剩 RGB 没 A”;
改回 4 后,步长重新按 16 字节切分,每个顶点正好读到自己的 RGBA,颜色恢复正常。
这说明 AI 关于“size 决定每顶点读几个分量、stride = 0 时按 size × sizeof(type) 自动切分”的解释是对的,能够对应我观察到的现象。
### 最终结论
gl.vertexAttribPointer 的参数不是“随便填”的,它精确描述了 GPU 该如何从连续内存中切出一个个顶点属性;位置的 size = 2 和颜色的 size = 4 分别对应 Shader 中 in vec4 vPosition 和 in vec4 vColor 的实际需要,任何一处不匹配都会造成读取错位。我之前以为 size 只是“填几个都行、GPU 会自己补齐”,经过对照实验后修正为:size 必须与 Shader 中该属性期望的分量数一致,否则数据读取就会错位,A 分量并不会被自动补上。

实验 1:gl.LINE_STRIP
我修改了什么:把 draw mode 从 gl.TRIANGLE_STRIP 改成 gl.LINE_STRIP。
我原先预测:不会出现填充四边形,而是沿着顶点顺序连出一条折线;因为 LINE_STRIP 是把相邻顶点依次连线,所以不会闭合,也不会填充。
实际结果:Canvas 上出现一条折线,依次连接“左上 → 左下 → 右上 → 右下”,首尾不相连,图形内部没有被填充。
原因解释:LINE_STRIP 把顶点序列解释为一串线段,连接 (v0,v1)、(v1,v2)、(v2,v3),因此不闭合,也不做三角形填充。

实验 2:gl.POINTS
我修改了什么:把 draw mode 改成 gl.POINTS。
我原先预测:只会看到 4 个孤立的小点,分别对应 4 个顶点,没有任何连线或填充。
实际结果:Canvas 上只出现了 4 个离散的小点,位置正好对应 4 个顶点;点与点之间没有线,也没有面。
原因解释:POINTS 把每个顶点单独解释为一个点图元,不进行任何连接或填充

实验 3:gl.LINE_LOOP
我修改了什么:把 draw mode 改成 gl.LINE_LOOP。
我原先预测:与 LINE_STRIP 类似是折线,但会首尾相连,形成一个闭合四边形轮廓;仍然不会填充。
实际结果:Canvas 上出现一个闭合的四边形轮廓,首尾相连,内部没有被填充。
原因解释:LINE_LOOP 与 LINE_STRIP 相似,但会在最后一个顶点和第一个顶点之间再连一条线段,因此图形是闭合的。

实验 4:gl.TRIANGLES
我修改了什么:把 draw mode 改成 gl.TRIANGLES。
我原先预测:4 个顶点按每 3 个一组解释成三角形,第 4 个顶点会被忽略,因此只会看到 1 个三角形。
实际结果:Canvas 上只出现 1 个三角形,由前 3 个顶点 (v0,v1,v2) 组成,第 4 个顶点没有参与绘制。
原因解释:TRIANGLES 把顶点序列按每 3 个一组解释为三角形,多余的顶点被忽略;因此 4 个顶点只能画出 1 个完整三角形。

实验 5:gl.TRIANGLE_STRIP(任务2 使用的模式)
我修改了什么:把 draw mode 改回 gl.TRIANGLE_STRIP。
我原先预测:4 个顶点会组成 2 个相邻的三角形,从而拼成一个完整的填充四边形,与任务2结果一致。
实际结果:Canvas 上重新出现一个完整的填充四边形,颜色与任务2一致。
原因解释:TRIANGLE_STRIP 把相邻顶点两两组合,依次构成 (v0,v1,v2)、(v1,v2,v3) 两个三角形,它们共享一条边,拼成一个四边形