为什么VolatileImage没有set / getPixel()方法

时间:2013-10-12 18:57:56

标签: java 3d rendering

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

我有4个问题:

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

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

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

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

  5. 如果您有任何想法请告诉我。我无法继续使用这些信息制作我的游戏。我已经制作了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。

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

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

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

下面的来源是一个独立的例子。您可以将几乎所有的面食复制到您的项目中并运行它。

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

在构造函数中,我保存了app / game的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获取Graphics并在那里渲染我的缓冲区。如果我不冲洗(),则不会渲染任何内容。

@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可写光栅上绘制像素时,仍有一点开销。但是当我们更新屏幕时,我们会在使用易失性图像而不是使用缓冲图像时获得速度提升。

希望这可以帮助一些人。欢呼声。