Java2D性能问题
我对Java2D的性能有点奇怪。我知道sun.java2d.opengl VM参数可以为2D启用3D加速,但即使使用它也有一些奇怪的问题 以下是我运行的测试结果: 在JComponent上绘制带有32x32像素分幅的25x18地图Java2D性能问题,java,java-2d,Java,Java 2d,我对Java2D的性能有点奇怪。我知道sun.java2d.opengl VM参数可以为2D启用3D加速,但即使使用它也有一些奇怪的问题 以下是我运行的测试结果: 在JComponent上绘制带有32x32像素分幅的25x18地图 图像1=.bmp格式,图像2=A.png格式 不带-Dsun.java2d.opengl=true 120 FPS,使用.BMP图像1 13 FPS使用.PNG图像2 使用-Dsun.java2d.opengl=true 12 FPS使用.BMP图像1 700 FPS
图像1=.bmp格式,图像2=A.png格式 不带-Dsun.java2d.opengl=true 120 FPS,使用.BMP图像1
13 FPS使用.PNG图像2 使用-Dsun.java2d.opengl=true 12 FPS使用.BMP图像1
700 FPS,使用.PNG图像2 在没有加速的情况下,我假设我在软件中所做的每一个drawImage()都会发生某种转换,并且在.PNG的情况下会大大降低FPS。但是,为什么在加速的情况下,结果会切换(PNG实际上执行得非常快)?!疯狂 .BMP图像1被转换为类型为\u INT\u RGB的图像类型。PNG图像2被转换为类型为_CUSTOM的图像类型。为了在有opengl加速和没有opengl加速的情况下获得一致的速度,我必须创建一个新的BuffereImage,其图像类型为_INT_ARGB,并将图像1或图像2绘制到此新图像 以下是使用该工具运行的结果: 不带-Dsun.java2d.opengl=true 120 FPS,使用.BMP图像1
120 FPS,使用.PNG图像2 使用-Dsun.java2d.opengl=true 700 FPS,使用.BMP图像1
700 FPS,使用.PNG图像2 我真正的问题是,我是否可以假设TYPE_INT_ARGB将是所有系统和平台的本机映像类型?我假设这个值可能不同。有没有什么方法可以让我获得本机值,这样我就可以始终创建新的BuffereImage以获得最佳性能
提前感谢…当我想到用Java进行图形编程时,我记得内置的库速度很慢。我在GameDev.Net上被告知,任何人做任何严肃的事情都必须使用类似于的东西。我想我找到了一个解决方案,通过研究和整合太多谷歌搜索中的零碎信息 以下是评论和所有内容:
private BufferedImage toCompatibleImage(BufferedImage image)
{
// obtain the current system graphical settings
GraphicsConfiguration gfxConfig = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().
getDefaultConfiguration();
/*
* if image is already compatible and optimized for current system
* settings, simply return it
*/
if (image.getColorModel().equals(gfxConfig.getColorModel()))
return image;
// image is not optimized, so create a new image that is
BufferedImage newImage = gfxConfig.createCompatibleImage(
image.getWidth(), image.getHeight(), image.getTransparency());
// get the graphics context of the new image to draw the old image on
Graphics2D g2d = newImage.createGraphics();
// actually draw the image and dispose of context no longer needed
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
// return the new optimized image
return newImage;
}
在我之前的文章中,GraphicsConfiguration保存了在系统上创建优化图像所需的信息。它似乎工作得很好,但我原以为Java会自动为您做到这一点。显然,使用Java您不会感到太舒服。:)我想我最终还是回答了我自己的问题。哦,好吧,希望它能帮助我见过的一些人尝试将Java用于2D游戏。好吧,这是一篇老文章,但我想分享一下我关于使用Swing/AWT直接绘图而不使用BuffereImage的发现 当直接绘制到int[]缓冲区时,某些类型的绘图(如3D)效果更好。完成图像处理后,您可以使用ImageProducer实例(如MemoryImageSource)生成图像。我假设您知道如何直接执行绘图,而无需借助图形/图形2
/**
* How to use MemoryImageSource to render images on JPanel
* Example by A.Borges (2015)
*/
public class MyCanvas extends JPanel implements Runnable {
public int pixel[];
public int width;
public int height;
private Image imageBuffer;
private MemoryImageSource mImageProducer;
private ColorModel cm;
private Thread thread;
public MyCanvas() {
super(true);
thread = new Thread(this, "MyCanvas Thread");
}
/**
* Call it after been visible and after resizes.
*/
public void init(){
cm = getCompatibleColorModel();
width = getWidth();
height = getHeight();
int screenSize = width * height;
if(pixel == null || pixel.length < screenSize){
pixel = new int[screenSize];
}
mImageProducer = new MemoryImageSource(width, height, cm, pixel,0, width);
mImageProducer.setAnimated(true);
mImageProducer.setFullBufferUpdates(true);
imageBuffer = Toolkit.getDefaultToolkit().createImage(mImageProducer);
if(thread.isInterrupted() || !thread.isAlive()){
thread.start();
}
}
/**
* Do your draws in here !!
* pixel is your canvas!
*/
public /* abstract */ void render(){
// rubisch draw
int[] p = pixel; // this avoid crash when resizing
if(p.length != width * height) return;
for(int x=0; x < width; x++){
for(int y=0; y<height; y++){
int color = (((x + i) % 255) & 0xFF) << 16; //red
color |= (((y + j) % 255) & 0xFF) << 8; //green
color |= (((y/2 + x/2 - j) % 255) & 0xFF) ; //blue
p[ x + y * width] = color;
}
}
i += 1;
j += 1;
}
private int i=1,j=256;
@Override
public void run() {
while (true) {
// request a JPanel re-drawing
repaint();
try {Thread.sleep(5);} catch (InterruptedException e) {}
}
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// perform draws on pixels
render();
// ask ImageProducer to update image
mImageProducer.newPixels();
// draw it on panel
g.drawImage(this.imageBuffer, 0, 0, this);
}
/**
* Overrides ImageObserver.imageUpdate.
* Always return true, assuming that imageBuffer is ready to go when called
*/
@Override
public boolean imageUpdate(Image image, int a, int b, int c, int d, int e) {
return true;
}
}// end class
既然最大的性能惩罚实际上是调用DRAWMAGEL(),那么我会考虑450个FPS 700个调用。我必须用jogl写同样的东西,看看是否有显著的区别,但是在Java的最新版本中,Java2D已经取得了巨大的进步。这绝对是了不起的。它使我的代码运行得更快。非常感谢。我很抱歉在回答这个问题时耽搁太久。非常感谢!只是想知道是什么样的人否决了正确的回答。。。它是(i)关于Java2D的;(ii)关于绘画图像的高性能;(iii)关于渲染来自其他地方的图像(OpenGL、本机渲染器、软件渲染器等)。那么为什么要投否决票呢???
/**
* Get Best Color model available for current screen.
* @return color model
*/
protected static ColorModel getCompatibleColorModel(){
GraphicsConfiguration gfx_config = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().
getDefaultConfiguration();
return gfx_config.getColorModel();
}