【发布时间】:2016-03-18 09:13:16
【问题描述】:
我目前正在为我的city building game 项目开发一个网络客户端(HTML5 和 JavaScript)。客户端通过 SignalR 与用 C#/.NET 编写的 Web 服务器进行交互,所有游戏逻辑都驻留在该服务器上。
该实现需要相当大的地图,该地图由一组代表不同图层的画布元素实现。地图的实际绘制包括绘制 25x25px 的单元格,其中一些是动画的。这意味着在“2D 上下文”上发生了很多小的“drawImage”调用。
当前的实现在 Mozilla Firefox、Internet Explorer 和 Edge 中运行良好且流畅。然而,它在 Google Chrome 上非常慢,很可能是由于其硬件加速渲染的实现效果不佳。
瓦片单元 .PNG 图像的获取是通过从 Web 服务器下载它们并将它们存储在内存中的“图像”对象中来完成的。从那里,我在必要时将它们直接绘制到画布上。 如果我目前的研究做得正确,这就是瓶颈所在;源“图像”对象驻留在 CPU 内存中,而目标 Canvas 元素针对 GPU 内存访问进行了优化,导致大量交换。
我尝试将“图像”对象移动到一个大的屏幕外“缓冲区”画布(足够大,以至于应该在 Chrome 上启动硬件加速),但这不会产生明显的差异: https://github.com/Miragecoder/Urbanization/commit/86ac62a785b233eea28c53b8a7d474ef92ffc283
我还尝试通过requestAnimationFrame 实现“drawImage”函数的延迟调用,但这也没有产生明显的差异。
我有以下问题:
- 我是否正确理解了这个问题?
- 如何提高 Web 客户端的性能?
一些我研究过但到目前为止没有结果的问题的链接:
【问题讨论】:
-
查看代码你不会强迫任何东西到 GPU 内存。如果没有空间,只有渲染才会将图像交换到 GPU 内存中。如果你对渲染顺序很小心,你会得到一些好处。即'ctx.drawImage(one,0,0); ctx.drawImage(二,0,0); ctx.drawImage(one,0,0); ' 将产生 3 次交换,而 'ctx.drawImage(one,0,0); ctx.drawImage(one,0,0); ctx.drawImage(二,0,0); ` 只会产生 2 个。较小的图像(整体的一部分)也会有所帮助。
-
嗨,Blindman67。渲染顺序到底是什么意思?例如,首先开始渲染底层然后向上移动?此外,“drawImage”调用小到 25x25 像素,所以我认为那里几乎不需要优化。感谢您的想法!
-
我不认为将图像放在另一个画布上对 gpu 有帮助。我不认为说“这些图像已经在 gpu 内存上,不需要重新上传它们”这样优化。优化绘图顺序似乎是最好的。你在所有gpus上都得到同样的慢?英伟达英特尔?
-
以下提交:github.com/Miragecoder/Urbanization/commit/… 执行以下操作: - 从大型缓冲区画布中提取 25x25 平铺图像(void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth , d高度);); - 按平铺图像对“drawImage”调用进行分组,并以有序的方式执行它们。我相信这是您和 Blindman67 都提出的方法。我认为它确实产生了一些显着的改进,但整体性能仍然很差。感谢您的建议!你还有吗?
标签: javascript google-chrome html5-canvas