34

我正在编写 Java 2D 游戏。我正在使用内置的 Java 2D 绘图库,在我从 JFrame 中的 Canvas 的 BufferStrategy 获得的 Graphics2D 上绘图(有时是全屏的)。BufferStrategy 是双缓冲的。重绘是通过计时器主动完成的。不过,我遇到了一些性能问题,尤其是在 Linux 上。

Java2D 有很多方法可以创建图形缓冲区和绘制图形,我只是不知道自己是否做对了。我一直在尝试 graphics2d.getDeviceConfiguration().createCompatibleVolatileImage,它看起来很有希望,但我没有真正的证据证明如果我将绘图代码切换到它会更快。

根据您的经验,在 Java 1.5+ 中将 2D 图形渲染到屏幕上的最快方法是什么?请注意,该游戏非常领先,因此我不想切换到完全不同的绘图方法,例如 OpenGL 或游戏引擎。我基本上想知道如何以最快的方式使用 Graphics2D 对象将内容绘制到屏幕上。

4

9 回答 9

34

这篇文章的答案、Consty 的答案以及我自己的研究的综合:

什么有效:

  • 用于GraphicsConfiguration.createCompatibleImage创建与您正在绘制的内容兼容的图像。这是绝对必要的!
  • 通过 使用双缓冲绘图Canvas.createBufferStrategy
  • 在可用的地方使用-Dsun.java2d.opengl=True以加快绘图速度。
  • 避免使用变换进行缩放。相反,缓存您要使用的图像的缩放版本。
  • 避免半透明图像!位掩码图像很好,但在 Java2D 中半透明非常昂贵。

在我的测试中,使用这些方法,我获得了 10 倍到 15 倍的速度提升,使正确的 Java 2D 图形成为可能。

于 2008-10-14T09:23:12.837 回答
16

我和你有同样的问题,我想。在这里查看我的帖子:

Java2D 性能问题

它显示了性能下降的原因以及如何修复它。但不能保证在所有平台上都能正常工作。你会在帖子中看到原因。

于 2008-10-13T07:23:08.977 回答
12

这里有一些小窍门。如果您更具体并且您正在尝试做什么,我可能会提供更多帮助。听起来像是一场游戏,但我不想假设。

只画你需要的!不要一直盲目地调用 repaint(),尝试一些兄弟姐妹,如 repaint(Rect) 或 repaint(x,y,w,h)。

使用 alpha 混合要非常小心,因为混合图像/基元可能是一项昂贵的操作。

尝试尽可能多地预渲染/缓存。如果您发现自己一遍又一遍地以相同的方式绘制圆,请考虑将其绘制到 BufferedImage 中,然后仅绘制 BufferedImage。您正在为速度而牺牲内存(典型的游戏/高性能图形)

考虑使用 OpenGL,使用 LWJGL 的 JOGL。JOGL 更像 Java,而 LWJGL 在 OpenGL 访问之上提供更多游戏功能。OpenGL 可以比 Swing 绘制数量级(使用适当的硬件和驱动程序)。

于 2008-10-01T11:50:38.310 回答
3

我认为还有一个尚未提及的重要内容:尽可能缓存所有内容的图像。如果您有一个在屏幕上移动的对象,并且它的外观没有太大变化,请将其绘制到图像上,然后在每一帧的新位置将图像渲染到屏幕上。即使对象是一个非常简单的对象,也要这样做——您可能会惊讶于节省了多少时间。渲染位图比渲染图元快得多。

您可能还想查看显式设置渲染提示,并在质量考虑允许的情况下关闭抗锯齿等功能。

于 2009-05-01T19:11:00.203 回答
1

我已经使用 Java 完成了一些基本的绘图应用程序。我没有做过任何图形密集型的工作,但我建议你好好处理所有的“重绘”调用。对父容器进行额外的重绘调用可能会使您的渲染量翻倍。

于 2008-09-29T12:50:44.563 回答
1

我一直在看这个问题,希望有人能给你比我更好的答案。

与此同时,我发现了以下Sun 白皮书,它是在 jdk 1.4 的 beta 版本之后编写的。这里有一些关于微调的有趣建议,包括运行时标志(在文章底部):

" Solaris 和 Linux 的运行时标志

从 SDK 的 Beta 3 版本 1.4 开始,当 DGA 不可用时,Java 2D 默认将图像存储在像素图中,无论您是在本地还是远程显示环境中工作。您可以使用 pmoffscreen 标志覆盖此行为:

-Dsun.java2d.pmoffscreen=true/false

如果将此标志设置为 true,即使 DGA 可用,屏幕外像素图支持也会启用。如果将此标志设置为 false,屏幕外像素图支持将被禁用。禁用屏幕外像素图支持可以解决一些渲染问题。"

于 2008-09-30T14:28:58.687 回答
0

确保使用双缓冲,首先绘制到内存中的一个大缓冲区,然后在所有绘制完成后刷新到屏幕。

于 2008-09-29T12:37:30.650 回答
0

您需要记住几件事

1) is refreshing this link显示了如何使用swingtimers,这可能是调用重绘的好选择。弄清楚重绘(正如之前的海报所说的那样很重要,所以你不会做太多的工作)。

2)确保您只在一个线程中进行绘图。从多个线程更新 UI 可能会导致令人讨厌的事情。

3) 双缓冲。这使得渲染更平滑。 这个网站有一些更好的信息给你

于 2008-09-29T13:17:21.800 回答
0

如果您不想使用纯 Java 2D,另一种选择是使用 GTGE 或 JGame 等游戏库(在 Google 上搜索它们),然后提供对图形的轻松访问,并提供双缓冲和更简单的绘图命令。

于 2008-11-17T05:22:21.263 回答