2011-06-25 18 views
11

Chciałbym wiedzieć, jak najlepiej obsługiwać operacje pikseli w Javie. Używam huśtawki i rysowanie prostokąta o wielkości 1 na 1 piksela jest strasznie powolne. Muszę uzyskać przynajmniej 60 fps, bez użycia zbyt dużej ilości zasobów. Czy blaknięcie obrazu może oznaczać, że uda się go pomyślnie zarchiwizować? Czy ogólnie jest to zły pomysł, aby zrobić to z Javą i czy muszę trzymać się C lub innej alternatywy?Obsługa szybkich pikseli Java

Jestem na początku pisania raycaster, a ponieważ openCL, którego używam, ma wrapper dla Java, wolę pracować w Javie.

+1

Sugerowałbym czytania na koncepcji obrazów pośrednich. Oto przykład - http://www.java2s.com/Code/Java/Advanced-Graphics/IntermediateImages.htm – mre

+0

Myślę, że technika Intermidiate Images jest zgodna z opisanymi przeze mnie liniami; zdruzgotanie obrazu. Jednak nie jestem zaznajomiony z prędkościami tego w Javie, o czym chcę wiedzieć. – RobotRock

+0

Ta technika nie dostanie 60 klatek na sekundę w Javie, wciąż zbyt wolno. – RobotRock

Odpowiedz

5

Dodawanie do sugestii @ camickr za:

Tworzenie BufferedImage (BI), owinąć je w IconImage, ustawić ją jako ikonę dla JLabel. Pomaluj zmiany w BI i wywołaj odświeżanie JLabel(), aby je przepłukać. zmiany na ekranie. Przechwytywanie częściowego obrazu w BI zmniejsza ilość pracy dla procedury malowania. Musi tylko rozmyć obraz, a nie renderować obraz. Użyj SwingWorkers, aby wdrożyć wątki tła, aby uruchomić obliczenia i przekazać wyniki z powrotem do EDT do malowania.

Dopóki mówimy o statycznym obrazie, to zadziała dobrze. Jeśli zastanawiasz się nad czymś bardziej przypominającym grę wideo (niektóre utrwalone obrazy i inne ruchome obrazy), spójrz na VolatileImage. Jest to dobry opis tutaj: http://gpwiki.org/index.php/Java:Tutorials:VolatileImage

Aktualizacja:

Poniżej przedstawiono mi trochę ponad 80 FPS:

public class Demo extends javax.swing.JPanel { 
    private Image src = null; 
    public Demo() { 
     new Worker().execute(); 
    } 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     if (src != null) g.drawImage(src, 0, 0, this); 
    } 
    private class Worker extends SwingWorker<Void, Image>{ 
     private final Color[] colors = { Color.red, Color.green, Color.blue }; 
     protected void process(List<Image> chunks){ 
      for (Image bufferedImage : chunks){ 
       src = bufferedImage; 
       repaint(); 
      } 
     } 
     protected Void doInBackground() throws Exception{ 
      int frames = 0; 
      int[] mem = new int[1024 * 768]; 
      long start = System.currentTimeMillis(); 
      long end = start + 15000; 
      long last = start; 
      while (last < end){ 
       int col = colors[frames % colors.length].getRGB(); 
       for (int y = 0; y < 768; y++) 
        for (int x = 0; x < 1024; x++) 
         mem[x + y * 1024] = col; 
       Image img = createImage(new MemoryImageSource(1024, 768, mem, 0, 1024)); 
       BufferedImage bi = new BufferedImage(1024, 768, BufferedImage.TYPE_INT_ARGB); 
       Graphics2D g2 = bi.createGraphics(); 
       g2.drawImage(img, 0, 0, null); 
       g2.dispose(); 
       publish(bi); 
       last = System.currentTimeMillis(); 
       frames++; 
      } 
      System.err.println("Frames = " + frames + ", fps = " + ((double) frames/(last - start) * 1000)); 
      return null; 
     } 
    } 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run(){ 
       JFrame jf = new JFrame(); 
       jf.getContentPane().add(new Demo(), BorderLayout.CENTER); 
       jf.setSize(1024, 768); 
       jf.setVisible(true); 
      } 
     }); 
    } 
} 
+0

Otrzymuję 10 klatek na sekundę wypełniając ekran pikselami na obrazie 1024x768. Masz pomysł, jak to przyspieszyć? Używam techniki podobnej do tej, którą powiedziałeś i uruchamiasz prawdziwą pętlę do renderowania. – RobotRock

+0

Jaki rodzaj wydajności otrzymasz, jeśli renderujesz tylko do BI i nie malujesz go na ekranie? Zazwyczaj wąskie gardła w śledzeniu ray są bardziej w obliczeniach niż aktualizacja ekranu. Spróbuj po prostu wypisać System.currentTimeMillis() za każdym razem, gdy wykonasz obliczenia na ekranie. –

+0

Rysuję nieskalowane piksele, więc po prostu wypełniam ekran piksel po pikselu. Przy 320x240 uzyskuję 100+ klatek na sekundę, przy 1024x768 spada do 10. Jeśli zostanę odmalowany(), to nie zmieni wyników. – RobotRock

4

Użyj metody BufferedImage i setRGB (...). Następnie narysuj cały obraz w swojej procedurze malowania.

+0

Czy mogę spełnić wymagania (60 fps) w ten sposób (przy rozdzielczości 1024x768)? – RobotRock