我一直在尝试使用these awesome tutorials来学习Web GL。我的目标是制作一个非常简单的2D游戏框架来取代基于画布的jawsJS。
我基本上只是希望能够创建一堆精灵并将它们移动,然后可能会在以后使用。
我整理了一个基本的演示,但是我遇到了一个我无法追踪的性能问题。一旦我到达屏幕上大约2000个精灵,帧速率坦克和我无法解决原因。与demo of the pixi.js webgl framework相比,它开始在约3万个兔子左右丢失帧数(在我的机器上),我有点失望。
My demo(framework source)有5002个精灵,其中两个正在移动,帧速率在厕所里。
我已经尝试通过pixi.js框架来尝试找出他们做的不同的事情,但它是500kloc并且做得比我多得多,我无法解决它。
我发现this answer基本上证实了我所做的大致是正确的 - 我的算法与答案中的算法几乎相同,但必须有更多的算法。
到目前为止,我尝试了一些方法 - 只使用一个'帧缓冲区',定义了一个形状,然后为每个精灵翻译5000次。这确实有助于帧速率,但没有关闭pixi演示(它意味着所有精灵必须是相同的形状!)。我删除了所有不移动的矩阵数学,所以也不是这样。这一切似乎都归结为drawArrays()
函数 - 它对我来说真的很慢,但仅限于我的演示!
我还尝试删除所有基于纹理的东西,用一个简单的块颜色替换片段着色器。它几乎没有任何区别,因此我将狡猾的纹理处理作为罪魁祸首。
我非常感谢能帮助我找到一些令人难以置信的愚蠢行为!
编辑:我肯定误解了一些关键点。我将整个事物剥离回基础,将顶点和片段着色器更改为超级简单:
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0, 1);
}
和
void main() {
gl_FragColor = vec4(0,1,0,1); // green
}
然后将精灵设置为绘制到(0,0),(1,1)。
使用5000个精灵,绘制一个帧需要大约5秒钟。这是怎么回事?
答案 0 :(得分:4)
使用WebGLInspector或chrome中的实验canvas inspector查看帧调用会显示完全未优化的渲染循环。
您可以而且应该使用同一个顶点缓冲区渲染所有几何体,
这样您就可以保存bindBuffer
以及vertexAttribPointer
来电。
您还可以保存99%的纹理绑定,因为您可以重复使用相同的纹理重新绑定。只要您不将其他东西绑定到同一个纹理单元,纹理就会保持绑定。
拥有状态缓存有助于避免绑定已绑定的数据。
看看my answer here关于作为状态机的gpu。
一旦优化了渲染循环,您就可以继续考虑以下事项:
答案 1 :(得分:1)
问题可能在于渲染中的这一行:glixl.context.uniformMatrix3fv(glixl.matrix, false, this.matrix);
。
根据我的经验,在每个模型中传递制服在webGL中非常慢,并且在大约1,000个独特模型之后我无法维持60FPS。不幸的是,webgl中没有统一的缓冲区来缓解这个问题。
我通过计算CPU上的所有顶点位置并使用一个drawArray
调用绘制所有顶点位置来解决我的问题。如果顶点数不是很大,这应该有效。我可以以60 FPS绘制2k移动+旋转立方体。我不记得你能以60 FPS绘制多少立方体,但它比2k高得多。如果这不够快,那么你必须调查drawArrayInstanced
。基本上,将所有矩阵存储在数组缓冲区上,并使用正确偏移量的drawArrayInstanced
调用绘制所有模型。
编辑:也是OP,如果你想看看PIXI如何进行顶点更新渲染(不是统一的实例化),请参阅https://github.com/GoodBoyDigital/pixi.js/blob/master/src/pixi/renderers/webgl/utils/WebGLFastSpriteBatch.js。