是否更新每帧上的整个VBO是绘制许多不断变化的独特三角形的最有效方法?

时间:2014-07-07 17:54:59

标签: opengl-es webgl

my previous question的答案建议我使用顶点缓冲区对象并将我的位置数据与我的颜色数据合并为一个数组,我现在在这个简单的测试用例中完成了这个:

http://jsfiddle.net/headchem/r28mm/14/

每帧的伪代码:

function drawFrame() {
    // clear global vertex[] array containing both position and color
    // recreate it with new triangles and colors (determined elsewhere)
    drawShapes();

    // put the vertex array into the VBO using gl.bufferData
    // finish with a single call to gl.drawArrays(gl.TRIANGLES, 0, numItems);
    render();
}

我知道没有银弹,但是我的目标是渲染一个充满变化的独特三角形的屏幕,这是最有效的方法吗?使用bufferSubData会比bufferData提供任何好处吗?

当我在动画循环中测试它时,我可以在帧速率受到影响之前每帧更新大约800个三角形。当我想在每一帧上都有独特的三角形变化时,这是我能做的极限吗?我看到人们抛出更大的数字,比如50k三角形 - 这是因为他们能够将他们的顶点阵列缓存在图形卡上而不需要改变每一帧上的每个顶点和颜色?当使用canvas api时,我可以在帧速率下降之前绘制1500个不同颜色和定位的矩形 - 我的WebGL错误地认为canvas api优于它吗?

1 个答案:

答案 0 :(得分:4)

我看了一下你的代码,你的JavaScript中有一点效率低下。例如,这行重复执行:

convertedVerts = convertedVerts.concat(getConvertedVerts(pxVerts, zIndex, color));

效率极低:程序的简单执行需要O(n ^ 2)时间,其中n是顶点数,因为每次该行运行时,它都会将元素复制到一个新数组中。

通过将其更改为以下内容,我在Firefox和Safari上的性能得到了很大改善(Chrome似乎并不关心,也许是因为它优化了复制):

convertedVerts.push.apply(convertedVerts, getConvertedVerts(pxVerts, zIndex, color));

更好的做法是更改getConvertedVerts,以便将数组推送到而不是创建并返回数组。

但是,编写程序的方式是分配Float32Array 一次,然后将新值直接写入其中(传递数组和起始索引)每一帧。避免创建新数组,特别是避免每帧都创建新的Float32Array,更不用说每个顶点。

我还建议你摆脱中间画布仿真步骤(比如构造一个rgba()颜色然后再解析它) - 没有理由在代码中有任何字符串操作,尽管这与上面的算法效率低下并不是一个问题。