我有一些代码可以在随机位置生成粒子,并以随机方向和速度移动。
每次迭代循环,我移动所有粒子,并在我的jpanel上调用重绘。
对于1,000个粒子,我每秒大约需要20到30帧。我计划最终拥有100,000到1,000,000个粒子。
在绘画中,如果窗口的大小发生变化,我只会创建一个新的bufferedimage。我将像素绘制到bufferedimage,然后调用drawImage来显示图像。
每个粒子都是一个像素,我已经确定所有的时间都用于实际绘制像素。因此,增加粒子数将大大降低帧速率。
我尝试过g.drawline(x,y,x + 1,y),img.setRGB(x,y,color),通过调用img.getRaster()获取像素数组.getDataBuffer()。 getData(),然后设置pixelData [y * width + x] = color。
我只能通过这些不同的绘制像素的方式获得帧速率的微小差异。
这是我的问题:绘制像素的最快方法是什么?是bufferedimage甚至是走的路吗?
感谢。
答案 0 :(得分:1)
我认为通过bufferedimage数据缓冲区的直接像素操作是使用标准库绘制内容的最快方法,因为您将图形对象开销降至最低。
但正如Perception所说,如果你想要显示100'000粒子或更多,你应该考虑使用OpenCl进行GPU编程。
答案 1 :(得分:1)
尝试使用java.awt.image.VolatileImage。它可以在没有任何CPU渲染的情况下用于全硬件加速。
答案 2 :(得分:1)
使用img.getRaster()。getDataBuffer()。getData()时,您应该在标准计算机上获得更快的帧速率。我知道这是因为我可以以每秒20-30帧的速度绘制整个屏幕,屏幕总共有1,000,000像素。我通过将渲染例程切成两半并使用两个线程来获得此速度。我的CPU是1.5ghz。
出于这个原因,我认为你可能在移动像素时出现了编码错误。请记住:创建新对象的操作比添加操作长100倍。另外看看你是否可以删除if语句。
另外,这可能很愚蠢,但我假设你每帧只调用一次img.getRaster()。getDataBuffer()。getData()?
相关说明,绘制多像素粒子自然需要很长时间。
答案 3 :(得分:0)
永远不要调用repaint();这是为了noobs,玩这个你不必调用repaint();.这种方法在过去的两个月里给我带来了太多的痛苦和不适,我很伤心没有人告诉我还有另一种方法。 1,000,000个粒子的实际速度非常快,因此您可能需要考虑蒙特卡罗方法,请参阅http://raytracey.blogspot.com/以获得更便宜的渲染选项。我不知道你是否可以承受所有这些颗粒的操纵,同时坚持20-30fps,我只是看了一个10秒的流体模拟,在2.4ghz 6gb ram机器上花了3个星期。我是apolagise因为我在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
}
}
答案 4 :(得分:0)
我看到设置BufferedImage数据的字节有了很大的改进。要做到这一点,你需要从BufferedImage获取数据,将其转换为字节数组,设置每个字节(根据图像的类型,字节排列会有所不同。例如:ARGB将有一个字节对于alpha,一个用于红色,一个用于绿色,一个用于蓝色。一个像素将是一个包含4个连续字节的块。) 详细了解如何获取数据here