在每一帧上更新整个VBO是绘制许多不断变化的独特三角形的最有效方法吗? [英] Is updating the entire VBO on each frame the most efficient way to draw many changing unique triangles?

查看:100
本文介绍了在每一帧上更新整个VBO是绘制许多不断变化的独特三角形的最有效方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的答案上一个问题建议我使用一个顶点缓冲对象",然后将位置数据与颜色数据合并到一个数组中,现在我已经在这个简单的测试用例中完成了此操作:

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个三角形.当我想要每帧上唯一且不断变化的三角形时,这是我只能做的限制吗?我看到人们扔很多更大的数字,例如5万个三角形-是因为他们能够在图形卡上缓存其顶点数组,而不需要更改每一帧的每个顶点和颜色?使用画布API时,我可以在帧率下降之前绘制1500个颜色和位置不同的矩形-我的WebGL在做错什么呢?我的WebGL表现得比画布API好吗?

解决方案

我查看了您的代码,您的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()颜色,然后再次对其进行解析)-尽管您的代码中根本没有任何字符串处理的理由这与上面的算法效率低几乎没有太大的关系.

Answers to my previous question suggested that I use a Vertex Buffer Object and merge my position data with my color data into a single array, which I have now done in this simple test case:

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

Pseudo code for every frame:

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();
}

I know there is no silver bullet, but for my goal of rendering a screen full of changing unique triangles, is this the most efficient way possible? Would using bufferSubData offer any benefit over bufferData?

When I tested this in an animation loop, I could update around 800 triangles per frame before framerate suffered. Is this the limit of what I can do when I want unique and changing triangles on every frame? I see people throwing around much larger numbers like 50k triangles - is that because they are able to cache their vertex array on the graphics card and don't need to change every vertex and color on every frame? When using the canvas api, I can draw 1500 differently colored and positioned rectangles before framerate dips - what am I doing wrong with my WebGL that the canvas api outperforms it?

解决方案

I took a look at your code and you've got a good bit of inefficiency in your JavaScript. For example, this line which is executed repeatedly:

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

can be extremely inefficient: a naïve execution of your program takes O(n^2) time where n is the number of vertices, because each time that line runs it copies elements into a new array.

By changing it to the following, I got much improved performance on Firefox and Safari (Chrome doesn't seem to care, perhaps because it optimizes the copying away):

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

Better still would be to change getConvertedVerts so that it takes the array to push onto rather than creating and returning one.

However, the way your program should probably be written is to allocate a Float32Array once, and then write new values directly into it (pass the array and a starting index around) in each frame. Avoid creating new arrays, and especially avoid creating new Float32Arrays, every frame, much less every vertex.

I would also recommend that you get rid of the intermediate canvas-emulation steps (like constructing an rgba() color and then parsing it again) — there is no reason to have any string-manipulation at all in your code, though this isn't nearly as much of an issue as the algorithmic inefficiency above.

这篇关于在每一帧上更新整个VBO是绘制许多不断变化的独特三角形的最有效方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆