5月29日 22:35

WebGL 缓冲区(Buffer)是什么?VBO 和 VAO 有什么区别?

WebGL 缓冲区就是 GPU 显存中的一块区域,用来存顶点数据(位置、颜色、法线、UV 等)。VBO(Vertex Buffer Object)是存数据的容器,VAO(Vertex Array Object)是记录"哪个 VBO 绑到哪个 attribute、偏移量多少、步长多少"的配置快照。WebGL 1 没有 VAO(需扩展 OES_vertex_array_object),WebGL 2 原生支持。有了 VAO,切换绘制对象只需 gl.bindVertexArray(vao) 一行,不用重复设置一堆 vertexAttribPointer

追问

VAO 具体记录了哪些状态?

每个 attribute 的启用状态(enableVertexAttribArray)、绑定的 VBO(vertexAttribPointer 时的 ARRAY_BUFFER)、数据偏移和步长、以及 ELEMENT_ARRAY_BUFFER 的绑定。不记录 ARRAY_BUFFER 本身的绑定——这点容易搞混。

为什么 WebGL 1 没有 VAO?

OpenGL ES 2.0 规范没包含 VAO,它从 OpenGL ES 3.0 / WebGL 2 才成为标准。WebGL 1 可以用扩展 OES_vertex_array_object,但不是所有设备都支持。项目兼容性要求高的话,自己封装一个 VAO 管理器,内部用数组存 attribute 配置,绑定时批量调用 vertexAttribPointer

EBO(IBO)和 VBO 什么关系?

EBO(Element Buffer Object)也叫 IBO,存索引数据,告诉 GPU 按什么顺序读顶点,实现顶点复用(一个正方体 8 个顶点而非 36 个)。EBO 绑定到 ELEMENT_ARRAY_BUFFER,绘制时用 gl.drawElements 而非 gl.drawArrays。EBO 的绑定状态记录在当前 VAO 里。

什么场景必须手动管理 Buffer?

动态更新的数据(粒子系统、变形动画)需要 gl.bufferData 分配大小后用 gl.bufferSubData 局部更新,避免每帧重新分配显存。静态数据(模型网格)创建一次即可,设 gl.STATIC_DRAW 提示驱动放显存。

多个 VBO 怎么组织到同一个 VAO?

同一个 VAO 绑定期间,依次 bindBuffer + vertexAttribPointer 注册每个 VBO 到不同的 attribute location。也可以把所有数据交错打包到一个 VBO 里(interleaved),用 stride 和 offset 描述布局,减少 buffer 切换次数。

标签:WebGL