JavaFX GrowableDataBuffer,Canvas性能出现问题

时间:2018-07-30 09:24:38

标签: java javafx javafx-8

因此,我有一个应用程序(游戏),该应用程序可以绘制许多分层的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部分-(如预期的那样)。即渲染器正在绘制两个图像到屏幕。据我在实践中可以发现的,打when是在跳过4个部分时发生的(即,绘制的单个图像覆盖了整个屏幕)。然后滚动中会出现明显的打h。有时这很重要,并且总是很明显。在更高的分辨率(超过4k)下,当2移到3个被跳过的部分时,会略微跳过。

图像的x尺寸为2800。太大,无法在非DX12卡上的一个呼叫中呈现。我的温度解决方案是强制执行另一个绘制调用,如您在注释代码部分中所见。这可以解决问题。我怀疑,这是一个完整的猜测,因为图形所需区域的大小增加了一倍,因此GrowableDataBuffer正在快速变化。我在GraphicsContext中戳了一下,这个“可能”似乎是问题的候补,因为它似乎会以n ^ 2的速度增长。

我的温度。该解决方案可能是可行的,因为即使以不同的分辨率绘制了不同数量的网格,在此大小下始终要求最少2片,仍将允许较大的n ^ 2纹理范围。但是,我更希望选择一种不太受黑客欢迎的解决方案。我确实尝试过访问缓冲区,但是它是受软件包保护的。

我想知道-这是否是问题-是否有任何建议去建议GrowableDataBuffer不要缩小并保持它更大的大小?也许有人知道是什么原因造成的。

1 个答案:

答案 0 :(得分:1)

“ hack”的另一种(但更合乎逻辑的)实现方式是也绘制那些稍微偏离屏幕并可能在接下来的几帧显示在屏幕上的背景图块:

for (Image anImage : image) {
    if ((x + offset + width) >= -RENDER_MARGIN && x + offset <= (canvasWidth + RENDER_MARGIN)) { 
        gc.drawImage(anImage, x + offset, y, width, height);
        drawn++;
    } else {
        segmentsSkipped++;
    }
    offset += width;
}

常量RENDER_MARGIN定义了一个瓦片可以在屏幕外显示多少像素。实际值取决于您的滚动速度。

但是,我建议使用GraphicsContext.drawImage(Image img, double sx, double sy, double sw, double sh, double dx, double dy, double dw, double dh)方法来改进渲染逻辑,以将GrowableDataBuffer保持恒定大小,该方法允许您定义源和目标区域,即仅绘制当前帧在屏幕上的图像的确切区域。

离题:我建议将背景图像分成较小的块,以减少内存使用量,并可能还提高整体渲染性能。