WebGL:优化每帧更改值和顶点计数的顶点缓冲区

pix*_*ike 6 javascript webgl opengl-es-2.0

我想实现一个顶点缓冲区的渲染器,每个帧都会在应用程序端更新.另外,顶点的数量(即,三角形的数量)也将每帧改变.

我的方法是将一次所需的最大值预先分配为Float32Array,然后仅更新更改的值,并使用bufferSubData更新缓冲区数据.然后通过从索引缓冲区发送一个范围来绘制我想要的那些.

作为一个最小的例子,假设我已经为Float32Array中的2个独立三角形分配了位置顶点,对于这个框架,我只想移动并绘制第二个三角形.我想我会这样做:

arrPos[9] += 1.0; // move the X coordinates in the Float32Array
arrPos[12] += 1.0;
arrPos[15] += 1.0;
gl.bindBuffer(gl.ARRAY_BUFFER, bufPos); // tell GL which buffer to use
gl.bufferSubData( gl.ARRAY_BUFFER, 3 * 3 * 4, arrPos ); // update the vertices - ERROR

// then just draw the 2nd traingle by sending its indices only
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufId); // tell GL which buffer to use
gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 3 * 2); // draw just this range
Run Code Online (Sandbox Code Playgroud)

问题是,bufferSubData抛出错误:"GL错误:GL_INVALID_VALUE:glBufferSubData:超出范围"

我已经尝试使用bufferSubData的偏移量3,9,12来解决它,但它们都给了我同样的错误.

另一个注意事项:如果我能够正常工作,在我看来,如果我想在重新使用这个预先分配的Float32Array的同时每帧绘制可变数量的三角形,我将需要更新END处的值数组,而不是开始,因为我只能指定bufferSubData的偏移量,而不是起始索引.我希望有人可以告诉我这种方法是否可行,或者如果我完全偏离轨道并且应该停止浪费我的时间.

pix*_*ike 3

好吧,我想我刚刚意识到问题是什么。我认为您不能指定 Float32Array 的范围来 bufferSubData;相反,它必须采用整个数组。(小于缓冲区的 Float32Array 可用于更新缓冲区的范围。)

换句话说,我认为每次要更新的顶点数量发生变化时都必须创建一个新的 Float32Array。这对我来说似乎效率很低,但我想事情就是这样。IMO 这种区别应该在 OpenGL 文档中得到更好的解释。

david van brink 建议使用 ArrayBufferView 创建 Float32Array 的子数组,从我最初的测试来看,它似乎有效。我以前的代码可以简单地通过执行以下操作来修复:

arrPos[9] += 1.0; // move the X coordinates in the Float32Array
arrPos[12] += 1.0;
arrPos[15] += 1.0;
var arrView = arrPos.subarray(9); // specify a range of the Float32Array
gl.bindBuffer(gl.ARRAY_BUFFER, bufPos); // tell GL which buffer to use
gl.bufferSubData( gl.ARRAY_BUFFER, 3 * 3 * 4, arrView ); // update the vertices

// then just draw the 2nd traingle by sending its indices only
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufId); // tell GL which buffer to use
gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 3 * 2); // draw just this range
Run Code Online (Sandbox Code Playgroud)