HTML5画布fillRect慢

7
我正在尝试使用HTML5画布编写简单的光线追踪器,但帧速率非常低。Firefox的分析器报告我的运行时80%用于context2d.fillRect(),我在地板和天花板上每列使用它,并在纹理墙上每像素使用它。我遇到了this这个问题,并发现fillRect在Chrome上比1x1像素图片快40%,在Firefox上快4%。他们提到fillRect仍在计算alpha内容,虽然如果alpha为1,则应该具有透明渲染的传递?是否有其他方法可以尝试使用JavaScript进行大量矩形和像素blitting?

1
Canvas 2d在浏览器中的性能尚未完全成熟,不同浏览器之间存在巨大差异。我相信它将来会得到改进。但在那之前,我建议使用上面提到的WebGL。我也确信它将完全取代Flash。 - Sir
@zacaj 请查看这个网站。他们有一个WebGL兼容性列表。当然,这并不考虑某些图形卡被列入黑名单的情况。 - wendelbsilva
2
需要看一些代码。根据您的实现方式,createImageData + putImageData 比 fillRect 快得多,这里有一个快速示例,可以显示超过20k个粒子:http://www.somethinghitme.com/projects/masspart/ - Loktar
继@wendelbsilva之后,ProcessingJS与WebGL配合使用非常好用。 - fartagaintuxedo
我不是很确定我理解你的问题,但如果我正确的话,这些链接可能对你有所帮助。1:http://gotoandlearn.com/play.php?id=144 2:http://jsperf.com/canvas-image-blitting - VivecVelothian
显示剩余6条评论
2个回答

3
我找到的解决方法是在每次调用时将fillRect()调用放入路径中:

我发现在每次调用时将fillRect()调用放入路径中是解决这个问题的一种方法:

canvasContext.beginPath();
canvasContext.rect(1, 1, 10, 10);
canvasContext.fill();
canvasContext.closePath();

看起来,如果不正确使用rect()的调用会添加到先前rect()调用的路径中,这可能导致内存泄漏或资源使用增加。


fillRect方法确实会创建一个临时的Path对象,但它不会添加任何内容到之前设置的路径中,在你的代码中调用closePath()是不必要的。 - Kaiido
当我在我的JS上运行分析器时,fill() + rect() 占用了约30%的空间,而仅使用 fillRect() 则占用了约20%的空间。 - Octopus
我不知道为什么这个有效,但它确实有效。在我的情况下,我发现用纯色替换我使用的图案也可以解决性能问题,但是当然,它看起来不对。这将绘图操作从仅填充小矩形需要 > 20ms 减少到 < 1ms,而没有任何视觉变化。 - Nathan Friedly

1

有两个解决方案可以尝试,以减少渲染时的CPU使用率。

第一种方法是尝试使用requestAnimationFrame方法,在浏览器准备好渲染画布时才进行渲染,特别是在用户打开画布标签页时。更多信息请参见:https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame

第二种方法是根据内容的部分或全部是否动态,使用JavaScript在内存中的其他“隐藏”画布上预先绘制画布的部分(例如,将主要画布分成4个子画布,然后在屏幕上只需绘制4个元素)。

备注:如果您使用Firefox浏览器进行多个画布渲染,则与Chrome相比,它会增加CPU使用率。

希望能对您有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接