簡體   English   中英

為什么VolatileImage沒有set / getPixel()方法

[英]Why does VolatileImage have no set/getPixel() method

我是游戲編程方面的新手。 我知道如何使用setPixel()將像素繪制到BufferedImage 在使用大尺寸格式時,速度非常慢,所以我繼續前進,找到了VolatileImage (花了我一周左右的時間)。 繪制線條,字符串,矩形等非常容易,但我無法繪制單個像素。 我已經嘗試過使用drawLine(x,y,x,y)但是在800x600的圖像上可以獲得3-4 FPS。 Java在VolatileImage沒有包含setPixel()setRGB()的事實使我非常生氣和困惑。

我有四個問題:

  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。

好吧,您基本上是在使用CPU繪制一個像素。 沒有辦法可以加速,因此這種方法對於VolatileImage根本沒有任何意義。 您得到的低FPS暗示這甚至會造成很大的開銷,因為每個像素繪制操作都發送到圖形卡(帶有位置和顏色等信息),這比修改3或4個字節的RAM需要更長的時間。

我建議要么停止分別繪制每個像素,要么想出一種方法使繪圖算法直接在圖形卡上運行(這很可能需要Java以外的其他語言)。

此帖子獲得答案已經有4年了。 我也在尋找這個問題的答案,並偶然發現了這篇文章。 經過更多搜索后,我開始使用它。 在下面,我將發布源代碼以使用VolatileImage渲染像素。

似乎Java隱藏了我們直接將像素繪制到VolatileImage的功能,但是我們可以向其繪制緩沖的圖像。 有充分的理由。 使用軟件繪制像素並不能真正幫助加速(在Java中看來)。 如果您可以將像素繪制到BufferedImage上,然后在VolatileImage上進行渲染,則可能會獲得速度上的好處,因為從該點開始硬件已加速。

下面的來源是一個獨立的示例。 您幾乎可以將所有內容復制粘貼到您的項目中並運行它。

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

在構造函數中,我保存了應用程序/游戲的圖形環境。

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並在那里渲染緩沖區。 如果我不flush(),什么也不會渲染。

@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可寫柵格上繪制像素時,仍然會有一點開銷。 但是,當我們更新屏幕時,使用揮發性圖像而不是緩沖圖像時,速度得到了提高。

希望這可以幫助一些人。 干杯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM