【问题标题】:Can't accelerate pixel-modified BufferedImages无法加速像素修改的 BufferedImages
【发布时间】:2013-10-17 14:46:05
【问题描述】:

很长一段时间,1-2 个月,我一直试图找到这个特定问题的答案:

我的图像硬件无法加速!

我一直在网上搜索,创建了自己的方法,用键盘敲击我的头(仍然感到疼痛)但没有成功。

虽然我讨厌 Java SDK 以外的库,但我尝试了 LWJGL 和 JOGL,但由于某些愚蠢的原因,它们无法在我的计算机上运行。

我尝试使用System.setProperty("Dsun.java2d.opengl", "True"),我使用了 VolatileImage,但我无法为其绘制单个像素。(我尝试使用drawLine(x,y,x,y),但速度很慢)

现在我很绝望。我会做任何事情来解决这个问题!所以,如果你知道解决方案(我知道你们中的一些人知道)请告诉我,这样我就可以解决这个问题。

我的代码:

   public static void render(int x, int y, int w, int h, ) {

            int a[] = new int[3]; // The array that contains RGB values for every pixel
            BufferedImage bImg = Launcher.contObj.getGraphicsConfiguration().createCompatibleImage(800, 600, Transparency.TRANSLUCENT); // Creates an image compatible to my JPanel (Runs at 20-24 FPS on 800x600 resolution)
            int[] wr = ((DataBufferInt) bImg.getRaster().getDataBuffer()).getData(); // Contains the image data, used for drawing pixels
            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] = i * j % 256;
                    wr[i + j * bImg.getWidth()] = new Color(a[0], a[1], a[2]).getRGB(); // Sets the pixels from a[]
                }
            }
            bImg.flush();
            g.drawImage(bImg, x, y, w, h, null); // Draws the image on the JPanel
            g.dispose();
            System.out.println(bImg.getCapabilities(Launcher.contObj.getGraphicsConfiguration()).isAccelerated()); // Prints out whether I was successful and made the image accelerated or failed and made everything worse
        }

我希望你能理解代码。请以任何方式修改它以帮助我找到解决问题的方法。

注意:请不要发布有关外部库的任何内容,除非您完全确定没有它们我无法正常工作。

还有,是不是我的显卡不支持加速? (因为我看到了硬件加速适用于其他人但不适用于我的帖子)顺便说一句,它是 GeForce 430 GT。

提前致谢!

【问题讨论】:

  • 您希望将不断绘制像素的图像缓冲区移至 GPU 会带来什么样的性能提升?你知道,多次写入内存然后一次将整个内容转储到 GPU 比对 GPU 进行多次单独调用要快。
  • 你试过我贴的例子吗!

标签: java graphics 3d acceleration


【解决方案1】:

来源复制自:Java Hardware Acceleration not working with Intel Integrated Graphics

试试这个:

package graphicstest;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferStrategy;

public class GraphicsTest extends JFrame {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new GraphicsTest();
            }
        });
    }

    GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
    BufferCapabilities bufferCapabilities;
    BufferStrategy bufferStrategy;

    int y = 0;
    int delta = 1;

    public GraphicsTest() {

        setTitle("Hardware Acceleration Test");
        setSize(500, 300);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        setVisible(true);

        createBufferStrategy(2);
        bufferStrategy = getBufferStrategy();

        bufferCapabilities = gc.getBufferCapabilities();

        new AnimationThread().start();
    }

    class AnimationThread extends Thread {
        @Override
        public void run() {

            while(true) {
                Graphics2D g2 = null;
                try {
                    g2 = (Graphics2D) bufferStrategy.getDrawGraphics();
                    draw(g2);
                } finally {
                    if(g2 != null) g2.dispose();
                }
                bufferStrategy.show();

                try {
                    // CHANGE HERE, DONT SLEEP
                    //Thread.sleep(16);
                } catch(Exception err) {
                    err.printStackTrace();
                }
            }
        }
    }

    public void draw(Graphics2D g2) {
        if(!bufferCapabilities.isPageFlipping() || bufferCapabilities.isFullScreenRequired()) {
            g2.setColor(Color.black);
            g2.fillRect(0, 0, getWidth(), getHeight());
            g2.setColor(Color.red);
            g2.drawString("Hardware Acceleration is not supported...", 100, 100);
            g2.setColor(Color.white);
            g2.drawString("Page Flipping: " + (bufferCapabilities.isPageFlipping() ? "Available" : "Not Supported"), 100, 130);
            g2.drawString("Full Screen Required: " + (bufferCapabilities.isFullScreenRequired() ? "Required" : "Not Required"), 100, 160);
            g2.drawString("Multiple Buffer Capable: " + (bufferCapabilities.isMultiBufferAvailable() ? "Yes" : "No"), 100, 190);
        } else {
            g2.setColor(Color.black);
            g2.fillRect(0, 0, getWidth(), getHeight());
            g2.setColor(Color.white);
            g2.drawString("Hardware Acceleration is Working...", 100, 100);
            g2.drawString("Page Flipping: " + (bufferCapabilities.isPageFlipping() ? "Available" : "Not Supported"), 100, 130);
            g2.drawString("Full Screen Required: " + (bufferCapabilities.isFullScreenRequired() ? "Required" : "Not Required"), 100, 160);
            g2.drawString("Multiple Buffer Capable: " + (bufferCapabilities.isMultiBufferAvailable() ? "Yes" : "No"), 100, 190);
        }

        y += delta;
        if((y + 50) > getHeight() || y < 0) {
            delta *= -1;
        }

        g2.setColor(Color.blue);
        g2.fillRect(getWidth()-50, y, 50, 50);
    }
}

输出我得到硬件加速不可用。 java.exe 占用了 12% 的 CPU。 700 帧/秒

然后我添加了系统变量:

Variable name: J2D_D3D_NO_HWCHECK
         Variable value: true

然后重启IDE,运行程序:

我得到了惊人的结果。我有可用的硬件加速。 java.exe 占用了 5% 的 CPU。 1700 帧/秒。动画很棒!

以上是检查硬件加速是否在您的系统中工作。

现在回答您的问题:

AFAIK:您无法使用 BufferedImage 获得真正的硬件加速。您应该使用 VolatileImage 来获得硬件加速。但是使用 VolatileImage,您无法获取像素数据缓冲区来修改像素。而且使用硬件逐像素渲染是没有意义的。

我的建议:

1) 设计您的逻辑,该逻辑可以使用易失性图像的 Graphics 和 Graphics2D 渲染像素。但不要像画 1 像素的线条那样去作弊。

2) 使用缓冲策略,双/三缓冲。

3) 如果您想坚持使用 BufferedImage 来设置每个像素,请使用 BufferedImage 作为数据模型,同时在 volatile 图像上绘制绘制缓冲图像。如果您正在缩放图像,这将有很大帮助。

4) 缓存频繁渲染的图片。

5) 更好地编写代码,例如:

int wi = bImg.getWidth();
int he = bImg.getHeight();
for (int i = 0; i < wi; i++) {
    for (int j = 0; j < he; j++) {
        wr[i + j * wi] = ((i % 256) << 16) | ((i * j % 256) << 8) | (j % 256);
    }
}

6) 对于 sqrt()、sin()、cos() 等耗时的数学运算,缓存这些运算的结果并创建查找表。

【讨论】:

  • 这确实是加速了,但是 OP 在编辑像素时遇到了加速关闭的问题。
  • 其实我很久以前也在寻找这个问题的答案,从其他帖子中得到这个答案,激动不已,忍不住要帮助别人。
  • 其实这会帮助 OP 了解硬件加速是否在系统上工作!
  • 抱歉我的回复晚了。环境变量添加了 5 FPS(至少我认为是因为这个),但它仍然没有加速。关于使用 VolatileImage... 如果我不能更改像素,那么拥有 200 FPS 有什么意义?至少我想到的渲染算法必须能够修改单个像素才能工作。顺便说一句,我不知道您所说的“缓存图像”到底是什么意思。无论如何,感谢您的努力,也很抱歉给您带来麻烦。
  • 想象一下,您告诉硬件绘制 100x100 矩形(更高效)。另一种方式,您告诉 100x100 次硬件绘制矩形的每个像素(效率非常低)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-04
  • 2014-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多