什么是在Java中绘制像素的最快方法?

7
我有一些代码可以在随机位置生成粒子,并以随机方向和速度移动。每次循环迭代时,我移动所有粒子,并在我的jpanel上调用repaint。对于1000个粒子,我得到大约20到30帧每秒的速度。我计划最终拥有100,000到1,000,000个粒子。在paint中,只有在窗口大小改变时才创建一个新的bufferedimage。我将像素绘制到缓冲图像中,然后调用drawImage来显示图像。每个粒子都是一个单独的像素,我已确定所有时间都花在了实际绘制像素上。因此,增加粒子数量将极大地降低帧速率。我尝试过g.drawline(x,y,x + 1,y),img.setRGB(x,y,color),通过调用img.getRaster()。getDataBuffer()。getData()获取像素数组,然后设置pixelData [y * width + x] = color。这些不同的绘制像素方式只会稍微影响帧速率。我的问题是:绘制像素的最快方法是什么? bufferedimage是否是正确的选择?谢谢。

虽然可能与您想要的略有偏差,但您可能想尝试一些GPU编程技术。您可以阅读这里,了解使用OpenCL的百万粒子示例的适应情况。 - Perception
5个回答

1

我认为通过缓冲图像的数据缓冲区进行直接像素操作是使用标准库绘制图形最快的方法,因为可以将图形对象开销降至最低。

但正如Perception所说,如果您想显示100,000个或更多的粒子,则应考虑使用OpenCl进行GPU编程。

LWJGL是一个小巧易用的Java-OpenGL/CL/AL绑定库


1

1
我看到了在设置BufferedImage的数据字节方面的巨大改进。要做到这一点,您需要从BufferedImage中获取数据,将其转换为字节数组,设置每个字节(根据图像类型,字节排列将不同。例如:ARGB将具有一个alpha字节,一个红色字节,一个绿色字节,一个蓝色字节。一个像素将是4个连续字节的块)。 了解更多关于获取数据的信息here

1

当使用img.getRaster().getDataBuffer().getData()时,标准计算机的帧速率应该会更快。我知道这是事实,因为我可以在20-30帧每秒的速度下绘制整个屏幕,而屏幕总共有1,000,000个像素。我通过将渲染例程分成两部分并使用两个线程来获得这个速度。我的CPU是1.5ghz。

因此,我认为您可能在移动像素时犯了编码错误。请记住:创建新对象比添加操作长100倍。另外,请查看是否可以削减任何if语句。

此外,这可能很傻,但我假设您每帧只调用一次img.getRaster().getDataBuffer().getData()?

相关说明,绘制多像素粒子自然需要很长时间。


-2

永远不要调用repaint();那是给新手用的,尝试在不必调用repaint();的情况下玩弄它。这种方法在过去两个月中给我带来了很多痛苦和不适,我很遗憾没有人告诉我还有另一种方法。100万个粒子会变得非常昂贵,所以您可能需要考虑使用蒙特卡罗方法,参见http://raytracey.blogspot.com/以获取更便宜的渲染选项。我不知道您是否能够承受操作所有这些粒子并保持20-30fps的速度,我刚刚观看了一个10秒钟的流体模拟,它在一台2.4ghz 6gb内存的机器上花费了3周时间。我很抱歉,因为我在BufferedImage方面的唯一经验是导入.png文件以便使用Graphics g进行绘制。最近我曾经参与过一个非常计算密集的项目,并且由于时间紧迫,我无法加速我的程序,所以如果您也处于同样的困境,请尝试使用这个包pet;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import javax.swing.*;


public class pet extends JPanel implements MouseListener{
public static JFrame frame = new JFrame("frame");
public pet() throws IOException{
 setPreferredSize(new Dimension(870, 675));         //configuring panel
 addMouseListener(this);
}
public static void main(String[] args) throws IOException{
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JComponent newContentPane = new pet();
    newContentPane.setOpaque(true);
    frame.setContentPane(newContentPane);
    frame.pack();
    frame.setVisible(true);
    frame.addMouseListener(new pet());
}
public void paintRectangleAtPoint(Graphics g, int x, int y){
g.setColor(Color.BLACK);
g.drawRect(x, y, 100,100);
}
public void paintStuff(Graphics g, int x, int y){
g.setColor(Color.BLACK);
g.drawRect(x, y, 100,100);
}
@Override
public void mouseClicked(MouseEvent e) {
paintStuff(frame.getGraphics(),e.getX(), e.getY());

}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub

}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub

}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub

}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub

}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接