问题
I have some code that generates particles at random locations, and moving in random directions and speed.
Each iteration through a loop, I move all the particles, and call repaint on my jpanel.
For 1,000 particles, I'm getting around 20 to 30 frames per second. I plan to eventually have 100,000 to 1,000,000 particles.
In paint, I only create a new bufferedimage if the window has changed size. I draw the pixels to the bufferedimage, and then call drawImage to display the image.
Each particle is a single pixel, and I have determined that all the time is taken up actually drawing the pixels. So, increasing the number of particles will drastically reduce the frame rate.
I've tried g.drawline(x,y,x+1,y), img.setRGB(x,y,color), getting an array of pixels by calling img.getRaster().getDataBuffer().getData(), then setting pixelData[y*width+x] = color.
I only get a small difference in the frame rate with these different ways of drawing the pixels.
Here's my question: What is the fastest way to draw pixels? Is bufferedimage even the way to go?
Thanks.
回答1:
I think the direct pixelmanipulation via the databuffer of the bufferedimage is the fastest way to draw something with the standard-library because you reduce the graphics object overhead to a minimum.
But as Perception said if you want to display 100'000 particles or more you should consider the GPU programming with OpenCl.
LWJGL for a small and easy to use Java-OpenGL/CL/AL binding
回答2:
Try using java.awt.image.VolatileImage. It can potentially be used with full hardware acceleration without any CPU rendering.
回答3:
You should be getting a much faster frame rate on a standard computer when using the img.getRaster().getDataBuffer().getData(). I know this for a fact because I can paint the entire screen in 20-30 frames per second and the screen has 1,000,000 pixels total. I obtained this speed by cutting the rendering routine in two and using two threads. My CPU is 1.5ghz.
For this reason, I think that you may have made a coding error in moving the pixels. Remember: creating a new object is a 100x times longer operation than addition. Also see if you can cut out any if statements.
Also, this may be silly, but I assume you are only calling img.getRaster().getDataBuffer().getData() once per frame?
On a related note, Drawing multi pixel particles will naturally take a long time.
回答4:
I see a huge improvement in setting the bytes the data of a BufferedImage. To do that you'll need get the data from the BufferedImage, turn it into a byte array, set each byte (depending on the type of the image, the byte arrangement will be different. For example: ARGB will have one byte for alpha, one for red, one for green, one for blue. One pixel will be a block of 4 consecutive bytes.) Read more about getting the data here
回答5:
Never call repaint(); that's for noobs, play around with this where you don't have to call repaint();. That method has caused me so much pain and discomfort in the last 2 months, and I am sad nobody told me there is another way. 1,000,000 particles will get expensive real fast, so you may want to consider a Monte Carlo method, see http://raytracey.blogspot.com/ for cheaper rendering options. I don't know if you can afford manipulation of all of these particles while adhering to 20-30fps, I just watched a 10 second fluid simulation that took 3 weeks on a 2.4ghz 6gb ram machine. I apolagise because my only experience in the BufferedImage is importing .png's to draw with Graphics g. I worked on a project that was very computationally expensive very recently and with the timeline I was not able to gpu accelerate my program, so if you're in the same boat, try this package 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
}
}
来源:https://stackoverflow.com/questions/13638793/what-is-the-fastest-way-to-draw-pixels-in-java