6

我有一些代码可以在随机位置生成粒子,并以随机方向和速度移动。

通过循环的每次迭代,我移动所有粒子,并在我的 jpanel 上调用 repaint。

对于 1,000 个粒子,我每秒的速度大约为 20 到 30 帧。我计划最终拥有 100,000 到 1,000,000 个粒子。

在绘画中,如果窗口大小改变,我只会创建一个新的缓冲图像。我将像素绘制到缓冲图像,然后调用 drawImage 来显示图像。

每个粒子都是一个像素,我已经确定所有时间都在实际绘制像素上。因此,增加粒子数量将大大降低帧速率。

我试过 g.drawline(x,y,x+1,y), img.setRGB(x,y,color),通过调用 img.getRaster().getDataBuffer().getData() 得到一个像素数组,然后设置 pixelData[y*width+x] = color.

通过这些不同的像素绘制方式,我在帧速率上只得到了很小的差异。

这是我的问题:绘制像素的最快方法是什么?缓冲图像甚至是要走的路吗?

谢谢。

4

5 回答 5

1

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

因此,我认为您可能在移动像素时出现了编码错误。请记住:创建新对象的操作比添加操作长 100 倍。另请参阅是否可以删除任何 if 语句。

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

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

于 2012-12-14T23:19:56.707 回答
1

尝试使用java.awt.image.VolatileImage。它可以在没有任何 CPU 渲染的情况下与完整的硬件加速一起使用。

于 2012-12-04T10:07:18.020 回答
1

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

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

LWJGL 用于小型且易于使用的 Java-OpenGL/CL/AL 绑定

于 2012-12-04T09:50:33.917 回答
1

我看到在设置 BufferedImage 数据的字节方面有了很大的改进。为此,您需要从 BufferedImage 中获取数据,将其转换为字节数组,设置每个字节(取决于图像的类型,字节排列会有所不同。例如:ARGB 将有一个字节用于 alpha ,一个代表红色,一个代表绿色,一个代表蓝色。一个像素将是一个由 4 个连续字节组成的块。)在此处阅读有关获取数据的更多信息

于 2016-05-07T19:26:18.580 回答
-2

永远不要调用 repaint(); 那是给新手的,在你不必调用 repaint(); 的地方玩这个。在过去的两个月里,这种方法给我带来了如此多的痛苦和不适,我很难过没有人告诉我还有另一种方法。1,000,000 个粒子会很快变得昂贵,因此您可能需要考虑蒙特卡罗方法,请参阅http://raytracey.blogspot.com/以获得更便宜的渲染选项。我不知道在坚持 20-30fps 的情况下你是否能负担得起所有这些粒子的操作,我刚刚观看了一个 10 秒的流体模拟,在 2.4ghz 6gb ram 机器上花了 3 周时间。我道歉是因为我在 BufferedImage 中的唯一经验是导入 .png 以使用 Graphics g 进行绘制。我最近参与了一个计算成本非常高的项目,并且由于时间线我无法加速我的程序,所以如果你在同一条船上,试试这个包宠物;

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

}
}
于 2016-01-27T03:04:47.710 回答