猿问

JavaFX GrowableDataBuffer,Canvas 性能问题

所以我有一个应用程序(一个游戏),它绘制了许多分层的 PNG 以显示在网格中。


    for (Image anImage : image) {

        if ((x + offset + width) >= 0 && x + offset <= canvasWidth) { 

            gc.drawImage(anImage, x + offset, y, width, height);

            drawn++;

        } else {

            segmentsSkipped++;

        }

        offset += width;

    }

    //        if (drawn == 1) gc.drawImage(image[0], x + offset, y, width, height);

这是快速移动并且是一个简单的循环。我在跑


-Djavafx.animation.fullspeed=true


我无法提供 SSCE,因为适当的示例需要滚动等和精灵才能正确再现。正如您在代码中看到的,为了减少绘制操作,我正在测试每个网格段是否在画布区域内,而不是在画布区域外绘制。这给了我大约 30FPS 的使用改进,但导致了一个奇怪的问题:通常在循环的每个循环中,在 4K 显示器上,渲染器“跳过”5 部分网格的 3 部分 - (如预期)。即渲染器正在向屏幕绘制两个图像。据我在实践中隔离,当跳过 4 个部分时会发生打嗝(即绘制一个填充整个屏幕的图像)。在滚动中有一个明显的打嗝。有时这很重要,而且总是引人注目。


图像大 2800 x。太大而无法在非 DX12 卡上的一次调用中呈现。我的温度 解决方案是强制执行另一个绘制调用,正如您在注释代码部分中看到的那样。这有助于解决问题。我的怀疑,这是一个完全的猜测,是 GrowableDataBuffer 正在迅速变化,因为图形所需区域的大小加倍。我在 GraphicsContext 中摸索了一下,这个“可能”似乎是问题的候选者,因为它似乎以 n^2 的速度增长。


我的温度 解决方案可能是可行的,因为即使在不同的分辨率下,绘制了不同数量的网格,在这个尺寸下总是需要最少 2 块,这将允许大 n^2 纹理的范围。但我更喜欢一个较少被黑客攻击的解决方案。我确实尝试访问缓冲区,但它受包保护。


我想知道 - 如果这是问题的话 - 无论如何建议 GrowableDataBuffer 不要缩小,并保持它的更大尺寸?或者也许有人知道是什么导致了这种情况。


FFIVE
浏览 241回答 1
1回答

慕哥9229398

你的“hack”的另一个(但更合乎逻辑的)实现是也绘制那些稍微离屏的背景图块,并且可以在接下来的几帧出现在屏幕上:for (Image anImage : image) {&nbsp; &nbsp; if ((x + offset + width) >= -RENDER_MARGIN && x + offset <= (canvasWidth + RENDER_MARGIN)) {&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; gc.drawImage(anImage, x + offset, y, width, height);&nbsp; &nbsp; &nbsp; &nbsp; drawn++;&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; segmentsSkipped++;&nbsp; &nbsp; }&nbsp; &nbsp; offset += width;}因此,常量RENDER_MARGIN定义了一个图块可以在屏幕外并仍被绘制的像素数。实际值取决于您的滚动速度。但是,我建议GrowableDataBuffer通过使用GraphicsContext.drawImage(Image img, double sx, double sy, double sw, double sh, double dx, double dy, double dw, double dh)允许您定义源区域和目标区域的方法来改进渲染逻辑以保持恒定大小,即仅绘制当前屏幕上的图像的确切区域框架。题外话:我建议将您的背景图像分成更小的块以减少内存使用并可能提高整体渲染性能。
随时随地看视频慕课网APP

相关分类

Java
我要回答