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

时间:2013-11-10 16:20:38

标签: javascript opengl-es-2.0 webgl

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

我的方法是将一次所需的最大值预先分配为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

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

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

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

最大的问题是gl.bufferSubData( gl.ARRAY_BUFFER, 3 * 3 * 4, arrPos );您将要在偏移量上传整个数组。这当然太大了。这篇文章已有几年历史了,但它可能对其他人有所帮助。

你可能正在寻找这个:

var offset = 3 * 3 * 4;
var count = 7 * 4;  // x1, y1, z1, x2, y2, z2, x3    (arrPos[9] -> arrPos[15])
gl.bufferSubData(this.gl.ARRAY_BUFFER, offset, arrView, offset, count);