如何在 WebGL 中实现 VBO 双缓冲?

How to implement VBO double buffering in WebGL?

我想通过设置 VBO 双缓冲来提高我的 WebGL 项目的性能。虽然有很多关于这个主题的文章,但我没能找到一篇有编码示例的文章。

我尝试了以下方法:

// Initial setup...

var buff1 = gl.createBuffer();
var buff2 = gl.createBuffer();
var buffActive = buff1;

// For each frame, change the verticies data and then ...

gl.bindBuffer(gl.ARRAY_BUFFER, buffActive);
gl.bufferData(gl.ARRAY_BUFFER, vertArray, gl.DYNAMIC_DRAW);
gl.drawArrays(gl.TRIANGLES, start, count);

buffActive = (buffActive === buff2) ? buff1 : buff2;

gl.bindBuffergl.bufferData 的调用工作正常。但是,gl.drawArrays 始终只使用来自 buff1 的数据进行渲染。我假设 gl.drawArrays 会使用当前绑定到 gl.ARRAY_BUFFER 的任何 VBO 进行渲染,但显然情况并非如此。

有人看到我遗漏了什么吗?

这里的问题是您将 buff1buff2 都绑定到同一个缓冲区 vertArray。 更好的做法是创建两个顶点数组(比如 vertArray1vertArray2)和 在初始设置期间将每个顶点数组绑定到一个单独的缓冲区对象(而不是每一帧,因为 bufferData() 销毁并重新初始化缓冲区对象的数据,这可能是一个 昂贵的操作,如果这样做需要将数据上传到 GPU)。

这是一个例子:

// Initial setup
var buff1 = gl.createBuffer();
var buff2 = gl.createBuffer();
// Associate the buffer data once during initial setup.
// Note that we use two vertex arrays, vertArray1 and vertArray2,
// rather than one
gl.bindBuffer(gl.ARRAY_BUFFER, buff1);
gl.bufferData(gl.ARRAY_BUFFER, vertArray1, gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, buff2);
gl.bufferData(gl.ARRAY_BUFFER, vertArray2, gl.DYNAMIC_DRAW);
var buffActive = buff1;
var vertArrayActive = vertArray1;

// For each frame:
gl.bindBuffer(gl.ARRAY_BUFFER, buffActive);
// No need to re-load the buffer data
gl.drawArrays(gl.TRIANGLES, start, count);
buffActive = (buffActive === buff2) ? Buff1 : buff2;
vertArrayActive = (vertArrayActive === vertArray2) ? VertArray1 : vertArray2;

如果您实施 VBO 双缓冲,那么您需要确保每次调用 gl.vertexAttribPointergl.enableVertexAttribArray 顶点属性数据(在 vertArray 中存储为交错数据) VBO 切换,而不仅仅是在设置期间。否则,您的顶点属性指针将始终引用第一个 VBO 中的数据,并且由于双缓冲,该 VBO 现在只会每隔一帧更新一次。现在必须在切换 VBO 之后和 gl.drawArrays.

之前调用 gl.vertexAttribPointergl.enableVertexAttribArray