Pixel eines BufferedImage bearbeiten (Performance)

Marlon

Mitglied
Hallo!
Ein sich in der Open Beta befindendes Echtzeitrollenspiel läuft flüssig mit relativ konstanten 40 fps.
Nun soll das bestehende Programm um Beleuchtungseffekte (Lichter und Schatten) erweitert werden und somit habe ich einen ersten Ansatz implementiert, welcher die Pixel eines BufferedImages (das Offscreen Image, welches über den gesamten Bildschirmbereich gelegt wird und Dunkelheit, Schatten und Lichter darstellen soll) auslesen und bearbeiten soll.
Allerdings führt folgende Einbindung dazu, dass das Spiel nicht mehr gleichmässig läuft (FPS nicht mehr konstant) und insgesamt viel langsamer:

Java:
	private void updateLightImage() {
		int[] pixel = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
		
        for(int p=0;p<pixel.length;p++) {
            pixel[p]=(brightness << 24) | (0 << 16) | (0 << 8) | 0;
        }
	}

Weiss jemand, wie man dieses Problem umgehen/besser lösen könnte. Oder hat jemand andere Tipps zu diesem Thema?
Vielen Dank im Vorraus!
Marlon
 
Hm ... ???:L Erstens müßte das ja nur gemacht werden, wenn 'brightness' sich ändert, und zweitens... warum manuell und Pixelweise? Ein einfaches
Code:
Graphics2D g = image.createGraphics();
g.setColor(colorWithBrightness);
g.fillRect(0,0,w,h);
g.dispose();
sollte es doch tun!?
 
das wäre mit Begründung überzeugender, wie soll das grundsätzlich betrachtet schneller sein?,
muss das nicht letztlich auch die Pixel-Werte des Arrays verändern? da wird ja wohl kaum System.arrayCopy() oder ähnliches intern helfen,
stattdessen noch der Overhead der Methodenaufrufe, des Graphics-Objekt usw.

das neue Pixel '(brightness << 24) | (0 << 16) | (0 << 8) | 0' kann man in diesem Fall vielleicht nur einmal ausrechnen,
aber das sieht mir eh nur nach einem Beispiel aus, und solcher Kleinkram wird nicht die Welt retten,

ich kann nicht wirklich hier etwas beitragen aber wenn dann ist so ein BufferedImage an sich die Grundquelle alles Langsamkeit und mit diesen Java-Mitteln nicht schnell zu bekommen?
 
Zuletzt bearbeitet von einem Moderator:
BufferedImages (vor allem die int-basierten) verwenden intern "Magie" (viel, viel, schwarze und kryptische Magie :shock: ). Nach außen hin wird glaubich unter dem Namen "Managed Images" zusammengefasst. Innen sind das höchst implementierungsspefifische Pipelines für die Maloperationen und ein (Grafik)speichermanagement, das auf Dinge zurückgreift, die von einem int[] Array schon sehr weit weg ist. Natürlich ist das immernoch kein "fundiertes Argument" dafür, dass ein fillRect schneller sein muss, aber... nach einigem Wühlen im Sun-Quellcode bin ich mir ganz unfundiert und subjektiv ziemlich sicher, dass das so ist 🙂 Kommt im Zweifelsfall auf einen Versuch an...

EDIT: Um es zumindest noch etwas weiter zu begründen:
Eine (leider sehr Alte) Quelle für die Bedenken: BufferedImage as Good as Butter, Part II | Java.net
Eine etwas neuere: Java Graphics: Code Snippets, Musings, and Discoveries: Images: Managed Images
Und eine von jemandem, der aus Erfahrung spechen dürfte: Java Image Processing - Managed Images and Performance

Der (etwas schwammige und grob vereinfachte, nagel' mich darauf nicht fest) Grundtenor ist, dass wenn man sich erstmal den Speicherbereich des Bildes für direkten Zugriff (als int[] Array) geholt hat, Sun intern nicht mehr so viele Möglichkeiten hat, das Bild z.B. im VRAM zu halten, und das eben die Performance in den Keller drücken kann. Aber wie gesagt, das war nur ein Hinweis - Ausprobieren und ggf. Sun-Code lesen könnte da noch mehr Einsichten oder Sicherheit bringen.
 
Zuletzt bearbeitet:
Hm ... ???:L Erstens müßte das ja nur gemacht werden, wenn 'brightness' sich ändert, und zweitens... warum manuell und Pixelweise? Ein einfaches
Code:
Graphics2D g = image.createGraphics();
g.setColor(colorWithBrightness);
g.fillRect(0,0,w,h);
g.dispose();
sollte es doch tun!?

Jetzt wird es interessant. 🙂
Ich muss ja erstmal alle Pixel "dunkel" machen (siehe brightness), um dann anschliessend die Stellen an denen Lichter stehen aufzuhellen, also den Alpha zu verändern.

Bilder sagen mehr als tausend Worte: http://www.asantee.net/ethanon/screenshots/eth075_3.jpg

Vielleicht gibt es aber auch tatsächlich eine Möglichkeit, dies eleganter zu lösen (ohne vorher jeden einzelnen Pixel anzupacken).

Edit: Ich möchte noch hinzufügen dass ich bei dem Spiel jedes Bild als BufferedImage UND als VolatileImage im Speicher halte. Gezeichnet werden natürlich (ultraschnell, mit bis zu 240 FPS) lediglich die VolatileImages, jedoch habe ich noch nicht herausgefunden ob und wenn dann wie es möglich ist, diese VolatileImages direkt zu verändern, so dass die Performance nicht in den Keller geht.

Edit2: Das Bild ist übrigens nicht von dem Spiel noch aus meiner Hand, es handelt sich um eine 2D Engine, welche ich im Netz gefunden habe und leider noch nicht fertiggestellt worden ist.
 
Zuletzt bearbeitet:
hübsches Bild,


nur um noch eine offensichtliche Frage zu stellen:
wie entstehen denn dort die Lichtquellen und die Schatten oder ist das bisher nur fest vorgegeben?

wenn das alles schon existiert (und nicht gerade deine Frage ist), dann sind das doch 100x aufwendigere Methoden als jetzt 5 Pixel zu ändern
 
Analog zum oben beschriebenen Verfahren würden sich für solche Punktförmigen Lichtquellen, die mit der Entfernung dunkler werden, dann vermutlich raidale "GradientPaint" anbieten...
 
Ich habe mich nun länger und intensiver mit dem oben genannten Problem befasst und nach Lösungen gesucht, ein BufferedImage (bzw. VolatileImage) ohne grossartigen Performanceverlust bei jedem Frameschritt zu bearbeiten und anzuzeigen.
Leider erfolglos!
Falls noch jemand weiter weiss oder sich mal intensiver mit dem Thema beschäftigt hat bin ich ihm unendlich dankbar, wenn er mir ein paar Hilfestellungen geben könnte!
 
Also ich vermute, wenn du wirklich jedes Pixel beleuchten willst (egal mit welchem Algorithmus), geht das in Echtzeit nur mit einem Shader in der Grafikkarte (also wenn du Java nimmst, OpenGL und GSGL).

Was du versuchen kannst sind Lightmaps. Also vorberechnete Tiles, die nur Alphainformationen enthalten und ueber die eigentlichen Textur-Tiles gezeichnet werden. Die generierst du einmalig am Anfang (z.B. 128 Stueck mit steigendem Alphawert) und speicherst pro Tile einen Helligkeitswert, anhand welchem du eine entsprechende Lightmap zeichnest. Aber auch hier wird wohl Java2D/Swing recht schnell in die Knie gehen.
 
Versuch mal folgendes:
ein halbtransparentes schwarz weeiß bild, das du über dein hauptbufferdeimage renderst. Dieses kann dann auch eine geringere auflösung haben was schonmal performance sparen sollte.
 
Ich kapier's nicht. Das hier malt ein Bild im dunkeln, und die Maus ist eine Taschenschlampe...
Java:
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.Point;
import java.awt.RadialGradientPaint;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


class LightEffectPanel extends JPanel implements MouseMotionListener
{   
    private Point point = new Point(0,0);
    private BufferedImage image;
    
    public LightEffectPanel()
    {
        BufferedImage i = null;
        try {
            i = ImageIO.read(new File("image.jpg"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        image = new BufferedImage(i.getWidth(), i.getHeight(), 
                BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = image.createGraphics();
        g.drawImage(i,0,0,null);
        g.dispose();
        addMouseMotionListener(this);
    }
    
    @Override
    protected void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D)gr;
        g.drawImage(image, 0,0,null);
        
        g.setComposite(AlphaComposite.SrcOver);
        Point2D center = new Point2D.Float(point.x, point.y);
        float[] dist = {0.0f, 1.0f};
        Color[] colors = {new Color(255,255,255,0), new Color(16,16,16,230) };
        RadialGradientPaint p =
             new RadialGradientPaint(
                center, 100, dist, colors, CycleMethod.NO_CYCLE);
        g.setPaint(p);
        g.fillRect(0,0,getWidth(),getHeight());
    }

    @Override
    public void mouseDragged(MouseEvent e) {
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        point = e.getPoint();
        repaint();
    }
}

class LightEffectTest
{
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new LightEffectTest();
            }
        });
    }
    
    
    public LightEffectTest()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(new LightEffectPanel());
        f.setSize(600,600);
        f.setVisible(true);
    }
    
}
Was genau meinst du? :bahnhof:
 
Danke für den Code, hat mir sehr geholfen!
Für ein einzelnes Licht funktioniert das ganze auch super und läuft recht fix, allerdings wird es problematisch, wenn mehrere Lichter (Kerzen, Lagerfeuer usw...) auf dem Bildschirm positioniert werden, da sich diese dann gegenseitig verdunkeln (es werden mehrere Bilder übereinander gezeichnet).
Gibt es eine Möglichkeit, meherere Lichtquellen mit diesem Verfahren darzustellen?
 
So ähnlich, nur schnell hingetippt, geht vielleicht auch eleganter...
Java:
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.Point;
import java.awt.RadialGradientPaint;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


class LightEffectPanel2 extends JPanel implements MouseMotionListener
{
    private Point point = new Point(0,0);
    private BufferedImage image;
    private BufferedImage shadow;

    public LightEffectPanel2()
    {
        BufferedImage i = null;
        try {
            i = ImageIO.read(new File("image.jpg"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        image = new BufferedImage(i.getWidth(), i.getHeight(),
                BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = image.createGraphics();
        g.drawImage(i,0,0,null);
        g.dispose();

        shadow = new BufferedImage(i.getWidth(), i.getHeight(),
                BufferedImage.TYPE_INT_ARGB);

        addMouseMotionListener(this);
    }

    @Override
    protected void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D)gr;
        g.drawImage(image, 0,0,null);

        drawLights();

        g.drawImage(shadow, 0,0, null);
    }

    private void drawLights()
    {
        Graphics2D g = shadow.createGraphics();
        g.setComposite(AlphaComposite.Src);
        g.setColor(new Color(0,0,16,240));
        g.fillRect(0,0,getWidth(),getHeight());

        drawLight(g, new Point(100,100));
        drawLight(g, point);

        g.dispose();
    }

    private void drawLight(Graphics2D g, Point pt)
    {
        float radius = 100;
        g.setComposite(AlphaComposite.DstOut);
        Point2D center = new Point2D.Float(pt.x, pt.y);
        float[] dist = {0.0f, 1.0f};
        Color[] colors = {new Color(255,255,255,255), new Color(0,0,0,0) };
        RadialGradientPaint p =
             new RadialGradientPaint(
                center, radius, dist, colors, CycleMethod.NO_CYCLE);
        g.setPaint(p);
        g.fillOval(pt.x-(int)radius,pt.y-(int)radius,(int)radius*2,(int)radius*2);
    }



    @Override
    public void mouseDragged(MouseEvent e) {
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        point = e.getPoint();
        repaint();
    }
}

class LightEffectTest2
{
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new LightEffectTest2();
            }
        });
    }


    public LightEffectTest2()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(new LightEffectPanel2());
        f.setSize(600,600);
        f.setVisible(true);
    }

}

EDIT: Die main hatte noch den alten Test gestartet. Jetzt stimmts. Danke an Fu3L für den Hinweis.
 
Zuletzt bearbeitet:
Hei super!
Zwar geht die Prozessorleistung total in den Keller, wenn das BufferedImage bearbeitet wird, jedoch habe ich deine hier beschriebene Funktionalität einfach auf ein VolatileImage angewendet und es funktioniert!
Die Menge der Lichter im Spiel (jedes Monster trägt eine kleine Fackel mit sich rum) spielt dabei gar keine Rolle.
Vielen vielen Dank!
 
Eine abschliessende Frage noch: Weisst du wie man das Programm umschreiben muss, damit die Lichtquellen nun auch eine Farbe ausstrahlen, das heisst den Leuchtkreis farblich verändern?
 
Ja, irgendwann wird's halt kompliziert. Grob was in der Richtung kann man mit
Java:
    private void drawLights()
    {
        Graphics2D g = shadow.createGraphics();
        g.setComposite(AlphaComposite.Src);
        g.setColor(new Color(0,0,16,240));
        g.fillRect(0,0,getWidth(),getHeight());

        drawLight(g, new Point(100,100), Color.WHITE);
        drawLight(g, point, new Color(250,190,0));


        g.dispose();
    }

    private void drawLight(Graphics2D g, Point pt, Color lightColor)
    {
        int radius = 100;
        Point2D center = new Point2D.Float(pt.x, pt.y);
        float[] dist = {0.0f, 1.0f};
        Color[] colors = {
            new Color(
                lightColor.getRed(),
                lightColor.getGreen(),
                lightColor.getBlue(),255),
            new Color(0,0,0,0) };
        RadialGradientPaint p =
             new RadialGradientPaint(
                center, radius, dist, colors, CycleMethod.NO_CYCLE);
        g.setPaint(p);
        g.setComposite(AlphaComposite.DstOut);
        g.fillOval(pt.x-radius,pt.y-radius,radius*2,radius*2);
        g.setComposite(AlphaComposite.SrcOver);
        g.fillOval(pt.x-radius,pt.y-radius,radius*2,radius*2);
    }
erreichen, aber eigentlich sollten sich die Lichthelligkeiten ja addieren.... da müßte man sich vielleicht was ausgefeilteres überlegen.
 
Ja danke erstmal! Leider führt das tatsächlich nicht zum erwünschten Ergebnis, da ja somit über den Hintergrund "drübergemalt" und somit verdeckt wird.

Vermutlich müsste man den Hintergrund gesondert anpacken und an den beleuchteten Stellen Farben "wegnehmen". Leider weiss ich nicht wie man das performant am besten angeht, da ich ja nicht wieder dahin gehen möchte jeden Pixel einzelnd zu bearbeiten.
 
Du solltest dir selbst klarmachen, was du willst, und wie das ganze aussehen soll.... Und das dann möglichst genau beschreiben. Rote Gegenstände sehen in grünem Licht schwarz aus, und Grüne weiß. Klingt komisch, ist aber so. Vielleicht muss man da noch irgendwo eine ColorConvertOp (Java Platform SE 6) einklinken, aber wie man das jetzt "physikalisch korrekt" berechnet (und das muss es zumindest ansatzweise sein, damit es es plausibel aussieht) weiß ich aus dem Stegreif auch nicht. Die Methode [c]void letMyRenderedStuffLookCool()[/c] gibt's halt in der Form noch nicht.
 
NOCH nicht.

Wieder einmal frage ich mich, warum ich das mache. Aber selbst deine zu erwartende Antwort ("Das ist so langsam ;( !", "Das braucht so viel Speicher ;( !", "Das sollte ein bißchen rötlicher sein ;( !") wird mich nicht davon abhalten, sowas in Zukunft weiterhin zu tun.

Java:
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.Point;
import java.awt.RadialGradientPaint;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


class LightEffectPanel4 extends JPanel implements MouseMotionListener
{
    private Point point = new Point(0,0);

    private BufferedImage inImage;
    private BufferedImage lightsImage;
    private BufferedImage lightImage;
    private BufferedImage outImage;

    public LightEffectPanel4()
    {
        inImage = loadInputImage();
        int w = inImage.getWidth();
        int h = inImage.getHeight();
        lightsImage = new BufferedImage(w,h,
                BufferedImage.TYPE_INT_ARGB);
        lightImage = new BufferedImage(w,h,
                BufferedImage.TYPE_INT_ARGB);
        outImage = new BufferedImage(w,h,
                BufferedImage.TYPE_INT_ARGB);

        addMouseMotionListener(this);
    }

    private BufferedImage loadInputImage()
    {
        BufferedImage i = null;
        try {
            i = ImageIO.read(new File("img.jpg"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        BufferedImage image = new BufferedImage(i.getWidth(), i.getHeight(),
                BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = image.createGraphics();
        g.drawImage(i,0,0,null);

        //g.setColor(Color.WHITE);
        //g.fillRect(0,0,i.getWidth(),i.getHeight());

        g.dispose();
        return image;
    }


    @Override
    protected void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D)gr;
        drawLights();
        multiply(inImage, lightsImage, outImage);
        g.drawImage(outImage, 0,0,null);
    }

    private void drawLights()
    {
        Graphics2D g = lightsImage.createGraphics();
        g.setColor(Color.BLACK);
        g.fillRect(0,0,lightsImage.getWidth(),lightsImage.getHeight());
        g.dispose();

        drawLight(point, new Color(255,230,128));
        drawLight(new Point(190,210), Color.RED);
        drawLight(new Point(160,180), Color.GREEN);
        drawLight(new Point(220,180), Color.BLUE);
    }

    private void drawLight(Point pt, Color color)
    {
        int radius = 100;
        Point2D center = new Point2D.Float(pt.x, pt.y);
        Color black = new Color(0,0,0,0);
        int steps = 10;
        float[] dist = new float[steps];
        Color[] colors = new Color[steps];
        boolean quadratic = true;
        for (int i=0; i<steps; i++)
        {
            float x = (float)i / (steps-1);
            dist[i] = x;
            float y = x;
            if (quadratic)
            {
                y *= x;
            }
            colors[i] = interpolate(color, black, y);
        }
        RadialGradientPaint p =
             new RadialGradientPaint(
                center, radius, dist, colors, CycleMethod.NO_CYCLE);

        Graphics2D g = lightImage.createGraphics();
        g.setColor(Color.BLACK);
        g.fillRect(0,0,lightImage.getWidth(),lightImage.getHeight());
        g.setPaint(p);
        g.fillOval(pt.x-radius,pt.y-radius,radius*2,radius*2);
        g.dispose();
        add(lightsImage, lightImage, lightsImage);
    }



    @Override
    public void mouseDragged(MouseEvent e) {
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        point = e.getPoint();
        repaint();
    }


    private static Color interpolate(Color c0, Color c1, float t)
    {
        int a0 = c0.getAlpha();
        int r0 = c0.getRed();
        int g0 = c0.getGreen();
        int b0 = c0.getBlue();
        int a1 = c1.getAlpha();
        int r1 = c1.getRed();
        int g1 = c1.getGreen();
        int b1 = c1.getBlue();
        int da = a1-a0;
        int dr = r1-r0;
        int dg = g1-g0;
        int db = b1-b0;
        int a = (int)(a0 + da * t);
        int r = (int)(r0 + dr * t);
        int g = (int)(g0 + dg * t);
        int b = (int)(b0 + db * t);
        return new Color(r,g,b,a);
    }

    private static int[] getData(BufferedImage i)
    {
        Raster raster = i.getRaster();
        DataBuffer dataBuffer = raster.getDataBuffer();
        if (!(dataBuffer instanceof DataBufferInt))
        {
            throw new IllegalArgumentException(
                "Image does not have a DataBufferInt");
        }
        DataBufferInt dataBufferInt = (DataBufferInt)dataBuffer;
        int data[] = dataBufferInt.getData();
        return data;
    }

    private static int getA(int argb) { return (argb >> 24) & 0xFF; }
    private static int getR(int argb) { return (argb >> 16) & 0xFF; }
    private static int getG(int argb) { return (argb >>  8) & 0xFF; }
    private static int getB(int argb) { return (argb >>  0) & 0xFF; }
    private static int getARGB(int a, int r, int g, int b)
    {
        return (a << 24) | (r << 16) | (g << 8)  | (b << 0);
    }

    private static void multiply(BufferedImage i0, BufferedImage i1, BufferedImage result)
    {
        int data0[] = getData(i0);
        int data1[] = getData(i1);
        int dataResult[] = getData(result);

        int w = i0.getWidth();
        int h = i0.getHeight();
        for (int x=0; x<w; x++)
        {
            for (int y=0;y<h; y++)
            {
                int argb0 = data0[x+y*w];
                int a0 = getA(argb0);
                int r0 = getR(argb0);
                int g0 = getG(argb0);
                int b0 = getB(argb0);
                int argb1 = data1[x+y*w];
                int a1 = getA(argb1);
                int r1 = getR(argb1);
                int g1 = getG(argb1);
                int b1 = getB(argb1);
                int ar = (a0*a1) >> 8;
                int rr = (r0*r1) >> 8;
                int gr = (g0*g1) >> 8;
                int br = (b0*b1) >> 8;
                int argb = getARGB(ar, rr, gr, br);
                dataResult[x+y*w] = argb;
            }
        }
    }

    private static void add(BufferedImage i0, BufferedImage i1, BufferedImage result)
    {
        int data0[] = getData(i0);
        int data1[] = getData(i1);
        int dataResult[] = getData(result);

        int w = i0.getWidth();
        int h = i0.getHeight();
        for (int x=0; x<w; x++)
        {
            for (int y=0;y<h; y++)
            {
                int argb0 = data0[x+y*w];
                int a0 = getA(argb0);
                int r0 = getR(argb0);
                int g0 = getG(argb0);
                int b0 = getB(argb0);
                int argb1 = data1[x+y*w];
                int a1 = getA(argb1);
                int r1 = getR(argb1);
                int g1 = getG(argb1);
                int b1 = getB(argb1);
                int ar = Math.min(255, a0+a1);
                int rr = Math.min(255, r0+r1);
                int gr = Math.min(255, g0+g1);
                int br = Math.min(255, b0+b1);
                int argb = getARGB(ar, rr, gr, br);
                dataResult[x+y*w] = argb;
            }
        }
    }


}

class LightEffectTest4
{
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new LightEffectTest4();
            }
        });
    }


    public LightEffectTest4()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(new LightEffectPanel4());
        f.setSize(600,600);
        f.setVisible(true);
    }

}
 
Ich danke dir vielmals für deine erneute Hilfe!!!
Das ist ja schon eine ganze Menge und daraus lässt sich sicher etwas schöpfen!
Aber ich muss schliesslich ehrlich sein: Für meine Zwecke ist das zu langsam 🙁 ..
Bei dem Vorgang auf jeden Pixel zuzugreifen geht die Performance in die Knie.
Ich hoffe ich werde in den nächsten Tagen etwas hinbekommen, ansonsten fahre ich das nächste Update erstmal ohne Farben.
Nochmal DANKE! 🙂
Marlon
 
Je nachdem, was langsam ist, könnte man noch ein bißchen was (oder ggf. sehr viel) einsparen. Das hängt von der größe der Lichter ab. Im Moment werden die Lichter in ein Bild gemalt, das so groß ist, wie das original. Eigentlich müßte das 'lightImage' aber nur radius*radius groß sein, und dann eben an die passende Stelle eingefügt. Wie groß sind die Lichter denn? (Und um wie viele Lichter geht es?)

Ansonsten behaupte ich mal, dass man es mit reinem Java3D (d.h. ohne OpenGL etc.) in dieser Form nicht viel schneller bekommt.
 

Zurück
Oben