1

我是游戏编程的相对新手。我知道如何将像素绘制到BufferedImageusing setPixel(). 较大格式的速度非常慢,所以我继续前进并发现VolatileImage(花了我一周左右的时间)。绘制线条、字符串、矩形等相当容易,但我无法绘制单个像素。我已经尝试过使用drawLine(x,y,x,y),但我在 800x600 图像上获得 3-4 FPS。java 没有包含setPixel()或包含setRGB()在其中的事实VolatileImage让我非常生气和困惑。

我有4个问题:

  1. 有没有办法在 VolatileImage 上绘制单个像素?(在 FPS > 40 的 1440x900 格式上)

  2. 我可以用更快的方法在 BufferedImage 中绘制像素吗?(相同的 1440x900,FPS > 40)

  3. 有没有其他方法可以为 3D 游戏快速绘制像素?

  4. 我可以让我的 BufferedImage 硬件加速吗(尝试使用setAccelerationPriority(1F)但它不起作用)

如果您有任何想法,请告诉我。没有这些信息,我无法继续制作我的游戏。我已经制作了 3D 渲染算法,但我需要能够绘制快速像素。我对这个游戏有很好的感觉。

如果它可以帮助你帮助我,这是代码:

public static void drawImageRendered (int x, int y, int w, int h) { // This is just a method to test the performance

    int a[] = new int[3]; // The array containing R, G and B value for each pixel
    bImg = Launcher.contObj.getGraphicsConfiguration().createCompatibleImage(800, 600); // Creates a compatible image for the JPanel object i am working with (800x600)
    bImg.setAccelerationPriority(1F); // I am trying to get this image accelerated
    WritableRaster wr = bImg.getRaster(); // The image's writable raster
    for (int i = 0; i < bImg.getWidth(); i++) {
        for (int j = 0; j < bImg.getHeight(); j++) {
            a[0] = i % 256;
            a[2] = j % 256;
            a[1] = (j * i) % 256;
            wr.setPixel(i, j, a); // Sets the pixels (You get a nice pattern)
        }
    }
    g.drawImage(bImg, x, y, w, h, null);
}

我宁愿不使用OpenGL或任何其他外部库,只使用普通的 Java。

4

2 回答 2

1

好吧,您基本上是在使用 CPU一个接一个地绘制一个像素。这无法加速,因此这种方法对于 VolatileImage 根本没有任何意义。您得到的低 FPS 表明这甚至会导致显着的开销,因为每个像素绘制操作都会发送到显卡(带有位置和颜色等信息),这比修改 3 或 4 字节 RAM 所需的时间更长。

我建议要么停止单独绘制每个像素,要么想办法让你的绘图算法直接在显卡上运行(这很可能需要除 Java 之外的另一种语言)。

于 2013-10-13T16:29:41.970 回答
1

自从这篇文章得到答案以来,已经有 4 年多了。我也在寻找这个问题的答案,偶然发现了这篇文章。经过一番搜索,我得到了它的工作。下面我将发布使用 VolatileImage 渲染像素的源代码。

似乎 Java 隐藏了我们将像素直接绘制到 VolatileImage 的能力,但我们可以向它绘制缓冲图像。有充分的理由。使用该软件绘制像素并不能真正帮助加速(在 Java 中似乎)。如果您可以将像素绘制到 BufferedImage,然后在 VolatileImage 上渲染它,您可能会获得速度加成,因为它从那时起就进行了硬件加速。

下面的源代码是一个独立的示例。您几乎可以将其全部复制到您的项目中并运行它。

https://github.com/Miekpeeps/JavaSnippets-repo/blob/master/src/graphics_rendering/pixels_03/PlottingVolatile.java

在构造函数中,我保存了应用程序/游戏的 Graphics 环境。

private GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
private GraphicsConfiguration gc = ge.getDefaultScreenDevice().getDefaultConfiguration();

然后,当我调用一个方法来启用硬件时,我们会创建一个缓冲区。我将透明度设置为不透明。在我的小引擎中,我在管道中的另一个线程上处理透明度/alpha 混合。

public void setHardwareAcceleration(Boolean hw) 
{
    useHW = hw;
    if (hw)
    {
        vbuffer = gc.createCompatibleVolatileImage(width, height, Transparency.OPAQUE);
        System.setProperty("sun.java2d.opengl", hw.toString()); // may not be needed.
    }
}

对于我更新的每一帧,我从 VolatileImage 获取图形并在那里渲染我的缓冲区。如果我不刷新(),则不会渲染任何内容。

@Override
public void paintComponent(Graphics g) 
{
    if(useHW) 
    {
        g = vbuffer.getGraphics();
        g.drawImage(buffer, 0, 0, null);
        vbuffer.flush();
    } 
    else 
    {
        g.drawImage(buffer, 0, 0, null);
        buffer.flush();
    }
}

调用在 BufferedImage 可写光栅上绘制像素时仍然有一点开销。但是当我们更新屏幕时,使用 Volatile 图像而不是使用 Buffered 图像可以获得速度提升。

希望这可以帮助一些人。干杯。

于 2018-01-31T20:46:41.187 回答