顶点缓冲对象 Vertext Buffer Object(VBO)
在上一节中,我们只是简单提了一下,封装了两个函数 bindArrayBuffer 和 activateAttribute 用于绘制一个三角形。实际上这对应着 OpenGL 中的一个核心概念——顶点缓冲对象(Vertex Buffer Object, 简称VBO)。它用于在 GPU 中存储顶点数据,包括坐标、颜色、法线等描述顶点的信息。 不用每次绘制时都从 CPU 向 GPU 搬运数据,极大提高了渲染效率。

1. 构建缓冲对象
bindArrayBuffer(data) {
let gl = this.gl;
let vbo = gl.createBuffer();
if (!vbo)
return null;
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW);
return vbo;
}
在 WebGL 中对应着数据类型 WebGLBuffer,该类型的对象没有定义任何方法或者属性,我们必须通过渲染上下文来操作它。 上面的函数是我们在上一节中封装的函数 bindArrayBuffer,它大体上做了三件事情:
- 创建缓冲对象
gl.createBuffer
。显然,在使用 VBO 之前需要先创建一个对象出来。函数 createBuffer 用于构建一个新的 VBO 对象, 如果构建成功将返回一个 WebGLBuffer 对象,否则返回 null。我们将用局部变量 vbo 保存对象。对应的还有 gl.deleteBuffer(vbo) 用于删除构建出来的缓冲对象。 - 绑定缓冲对象
gl.bindBuffer
。该函数用于指定刚构建出来的 vbo 对象作用的缓冲类型。 这里我们选择的是ARRAY_BUFFER
,用于存储顶点数据,如位置、法线、颜色等信息。渲染时,顶点着色器会根据这个缓冲区确定各个顶点的属性。 除此之外,还有ELEMENT_ARRAY_BUFFER
,COPY_READ_BUFFER
,COPY_WRITE_BUFFER
等多种选择,详细可以参见 文档。 - 搬运数据到缓冲对象中
gl.bufferData
。最后,我们还需要通过 bufferData 接口完成数据的搬运工作。第二个参数就是我们要搬运的带有类型的数据, 第一个参数选择ARRAY_BUFFER
就会将数据搬运到刚刚构建的 VBO 中。最后一个参数gl.DYNAMIC_DRAW
表示该 VBO 将多次写入数据并多次渲染。除此之外,还有一种只指定缓存大小的接口gl.bufferData(target, size, usage)
。 后续可以再通过bufferSubData
来填充数据。
2. 应用缓冲对象
完成了数据的搬运操作之后,我们就需要告知 WebGL 将顶点缓冲对象中的数据填充到 attribute 修饰的变量中,以完成图形渲染的工作。
在下面的代码的第 3 行,我们通过接口 useProgram
指定当前的渲染上下文中使用的着色器程序,包括了顶点着色器和片段着色器。
activateAttribute(attrib, itemSize, type, stride = 0, offset = 0) {
let gl = this.gl; let program = this.program;
gl.useProgram(program);
let attr = gl.getAttribLocation(program, attrib);
gl.vertexAttribPointer(attr, itemSize, _gl_type_map_[type], false, stride, offset)
gl.enableVertexAttribArray(attr);
}
然后通过接口 getAttribLocation
获取指定名称的 attribute 变量在 WebGL 中的索引。当 WebGL 成功找到目标变量后,
就会返回一个32位的有符号整型(GLint)数据,否则将返回 -1。
上一节的例程调用 render.activateAttribute("a_position", 2, "float")
通过参数 "a_position" 指定顶点着色器通过上述构建的 VBO 对象获取顶点位置数据。
![]() |
接着,我们通过接口 vertexAttribPointer 告知 WebGL 应该如何使用缓冲中的数据, 关于该接口的参数的详细设置可以参考文档。 最后,通过调用接口 enableVertexAttribArray 开启 attribute 变量,使得顶点着色器能够访问缓冲中的数据。 此外,我们还可以通过接口 gl.disableVertexAttribArray 来关闭 attribute 变量。
3. 完成渲染
完成上述的数据搬运和 attribute 变量的指定之后,我们就可以调用 gl.drawArrays
完成几何图形的绘制。
有了 VBO 的顶点缓存对象的加持,我们可以先把大量的数据搬运到内存中,再通过 gl.bindBuffer
在各个VBO之间切换,绘制多个几何图形。
![]() |
上图是例程3的截图。我们先通过封装的函数 bindArrayBuffer 构建了两个缓冲对象 vbo0 和 vbo1,
它们分别是构成右上角和左下角两个三角形的顶点坐标。在接下来的程序中,我们在函数 useArrayBuffer 中,
直接调用接口gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
完成缓冲对象的切换。如此就可以先渲染右上角的绿三角,再渲染左下角的红三角。