CanvasRenderingContext2D.drawImage() 在大画布上的 Chrome 中非常慢

Rob*_*tra 6 javascript google-chrome html5-canvas

我目前正在为我的城市建设游戏项目开发 Web 客户端(HTML5 和 JavaScript)。客户端通过 SignalR 与用 C#/.NET 编写的 Web 服务器交互,所有游戏逻辑都驻留在该服务器上。

该实现需要相当大的地图,该地图由一组代表不同图层的画布元素实现。地图的实际绘制包括绘制 25x25px 的单元格,其中一些是动画的。这意味着在“2D 上下文”上发生了很多小的“drawImage”调用。

当前的实现在 Mozilla Firefox、Internet Explorer 和 Edge 中运行良好且流畅。然而,它在谷歌浏览器上非常慢,很可能是因为它的硬件加速渲染效果不佳。

瓷砖单元格 .PNG 图像的获取是通过从 Web 服务器下载它们并将它们存储在内存中的“图像”对象中来完成的。从那里,我在必要时将它们直接绘制到画布上。如果我目前的研究正确完成,这就是瓶颈所在;源“图像”对象驻留在 CPU 内存中,而目标画布元素针对 GPU 内存访问进行了优化,从而导致大量交换。

我曾尝试将“图像”对象移动到一个大的屏幕外“缓冲区”画布(足够大,以便硬件加速应该在 Chrome 上启动),但这不会产生明显的差异: https://github .com/Miragecoder/Urbanization/commit/86ac62a785b233eea28c53b8a7d474ef92ffc283

我还尝试通过requestAnimationFrame实现“drawImage”函数的延迟调用,但这也没有产生明显的差异。

我有以下问题:

  • 我是否正确理解了问题?
  • 我可以做些什么来提高 Web 客户端的性能?

一些指向我研究过但到目前为止没有结果的问题的链接:

小智 5

您的主要问题似乎是用于绘制到画布上的不同图像对象的数量。您绝对应该使用Textureatlas,将尽可能多的图形放入单个图像中。

然后,您应该通过指定相关的矩形,从尽可能少的主图像中渲染精灵:

void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
Run Code Online (Sandbox Code Playgroud)

而不是整个图像:

void ctx.drawImage(image, dx, dy);
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅CanvasRenderingContext2D.drawImage()。这样,您就可以避免过多的上下文切换。正如 Blindman67 提到的,您应该小心地尽可能少地在纹理图集之间切换 - 例如,您可能希望使用单个纹理图集来渲染 canvas1 的所有内容,使用另一个纹理图集来渲染 canvas2 的所有图像,等等。