【发布时间】:2014-10-23 17:59:54
【问题描述】:
我正在尝试使用 Java2D 在运行时使用某种体面的抗锯齿插值(例如双线性)来扩展后缓冲区。我的想法是我将场景渲染到这个图像,然后在全屏模式下放大图像以匹配用户拥有的任何分辨率。
请注意,全屏模式很重要。这在窗口模式下不会发生。
有没有使用硬件缩放的快速方法? Javadocs 建议它存在(-Dsun.java2d.ddscale=true),但它对我没有影响。
代码如下:
// Initialization in AWT Canvas
buffer_ = createImage(1280, 800);
// Several hundred large draw calls into the buffer that renders the entire scene - executes fast (~10ms)
drawScene(buffer_.getGraphics());
// Upscaling buffer to screen. If I don't upscale it executes very fast (<1ms)
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(buffer_, 0, 0, 1920, 1200, null);
结果:
- 最近邻(大约 2 毫秒)
- 双线性(约 40 毫秒)
- 双三次(约 140 毫秒)
图像是 TYPE_INT_RGB 不透明的 BufferedImage,我正在 AWT 画布上绘图。
我尝试过的其他方法:
- VolatileImage(性能无变化)
- Dsun.java2d.ddscale=true(无变化)
- Dsun.java2d.opengl=true(所有命令的速度大约慢 3 倍)
- 仿射变换(无变化)
- createBufferStrategy 并通过调用 Graphics2D.scale 进行“预缩放”(慢得多,缩放每个绘制调用而不是 1 个大缓冲区)。请注意,没有缩放的 BufferStrategy 无论如何都无法提高速度。
- JPanel 代替 Canvas(大约慢 1.5 倍)
- imgScalr “library”(这只是调用
g.drawImage,就像我上面所说的那样)
其他一些有用的说明:
-
buffer_.getCapabilities(gc).isAccelerated()返回false(在窗口模式下为true) - 这是遗留代码,我有更新的代码,全部是 GL,可以非常快速地进行缩放,但不想重写遗留程序。表明我的硬件确实支持图像的硬件缩放。
- AMD HD5770 显卡
- Windows 7 最新 Java 8 作为 JVM 运行。
感谢您的帮助。在这一点上,我很遗憾地考虑将所有东西都转换为 GL 只是为了这一件事......不过肯定有答案!
【问题讨论】:
-
附带说明:转换为 OpenGL(JOGL、LWJGL 或任何基于它们的框架)通常是具有灵活渲染管道(缩放、旋转、纹理过滤、各种 3D 效果、着色器、SIMD 并行计算等),所以如果你想获得 HQ/高速图形,只需使用 OpenGL。一旦掌握了它,重写将比尝试修复低级/原生 Java2D 实现花费更少的时间; AFAIR 他们多次尝试简化 Java 的加速,都以分叉结束,因为它对每个人来说都是如此皇家 PITA
-
当然!尽管对于这种大小的应用程序,我不同意重写会花费更少的时间。我过去在 GL 中编写了一个 2D 图层,并且对它非常满意,但是将其集成到此代码中需要数周时间。更不用说,它有自己的问题。我在下面粘贴的半解决方案(到目前为止)是我要使用的,只花了几天的时间就头痛并且运行速度非常快。老实说,我遇到的问题似乎是一个错误。甚至可能与驱动程序有关。在窗口中运行良好,在 FSEM 中失去硬件加速?太奇怪了。
标签: java