# jogl 2d performance



## Anony (9. Sep 2010)

tag die herren,

ich will ein 2d spiel mit hilfe von jogl programmieren. vom verständnis hab ich da kein wirkliches problem - jedoch mit der performance. hier mal ein ganz simples beispiel, mit grottiger performance:

```
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JTabbedPane;

import net.java.games.jogl.GL;
import net.java.games.jogl.GLCanvas;
import net.java.games.jogl.GLCapabilities;
import net.java.games.jogl.GLDrawable;
import net.java.games.jogl.GLDrawableFactory;
import net.java.games.jogl.GLEventListener;

public class classTest extends JFrame {
	public JTabbedPane tabbedPaneHandle = null;
	
	public GLCapabilities glCapabilitiesHandle = null;
	public GLCanvas glCanvasHandle = null;
	
	public static void main(String[] args) {
		new classTest();
	}
	
	public classTest() {
		this.setSize(800, 600);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		this.glCapabilitiesHandle = new GLCapabilities();
		
		this.glCapabilitiesHandle.setDoubleBuffered(true);
		this.glCapabilitiesHandle.setHardwareAccelerated(true);
		
		this.glCanvasHandle = GLDrawableFactory.getFactory().createGLCanvas(this.glCapabilitiesHandle);
		
		class glEventListenerCustomized implements GLEventListener {
			public void init(GLDrawable arg0) {
				GL gl = arg0.getGL();
				
				gl.glMatrixMode(GL.GL_PROJECTION);
				gl.glLoadIdentity();
				gl.glViewport(0, 0, 800, 600);
				gl.glOrtho(0.0, 800.0, 600.0, 0.0, 0.0, 128.0);
				
				gl.glMatrixMode(GL.GL_MODELVIEW);
				gl.glLoadIdentity();
			}
			
			public void display(GLDrawable arg0) {
				GL gl = arg0.getGL();
				
				gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
				
				for (int intFor01 = 0; intFor01 < 20; intFor01 += 1) {
					for (int intFor02 = 0; intFor02 < 20; intFor02 += 1) {
						try {
							if ((intFor01 % intFor02 % 3) == 0) {
								gl.glColor3d(0.0, 1.0, 0.0);
								
							} else if ((intFor01 % intFor02 % 3) == 1) {
								gl.glColor3d(1.0, 0.0, 0.0);
								
							} else if ((intFor01 % intFor02 % 3) == 2) {
								gl.glColor3d(0.0, 0.0, 1.0);
								
							}
							
							gl.glBegin(GL.GL_QUADS);
							
							gl.glTexCoord2i(0, 0);
							gl.glVertex3i(intFor01 * 32, intFor02 * 32, 0);
							gl.glTexCoord2i(0, 1);
							gl.glVertex3i(intFor01 * 32 + 32, intFor02 * 32, 0);
							gl.glTexCoord2i(1, 0);
							gl.glVertex3i(intFor01 * 32 + 32, intFor02 * 32 + 32, 0);
							gl.glTexCoord2i(1, 1);
							gl.glVertex3i(intFor01 * 32, intFor02 * 32 + 32, 0);
							
							gl.glEnd();
						} catch (Exception e) {
						}
					}
				}
				
				gl.glFlush();
			}
			
			public void displayChanged(GLDrawable arg0, boolean arg1, boolean arg2) {
			}
			
			public void reshape(GLDrawable arg0, int arg1, int arg2, int arg3, int arg4) {
			}
		}
		
		this.glCanvasHandle.addGLEventListener(new glEventListenerCustomized());
		
		this.add(this.glCanvasHandle);
		
		this.setVisible(true);
		
		new Thread() {
			public void run() {
				do {
					classTest.this.glCanvasHandle.display();
				} while (true);
			}
		}.start();
	}
}
```

weis von euch jemand warum das so langsam ist? doublebuffer?

danke schon mal - anony


----------



## maki (9. Sep 2010)

> weis von euch jemand warum das so langsam ist?


Deswegen:

```
do {
                    classTest.this.glCanvasHandle.display();
                } while (true);
```
ein Sleep wäre angebracht.


----------



## Anony (9. Sep 2010)

in meinem nicht geschnittenen und für das forum als beispiel angepassten source ist ein frame limiter mit drin - genauso grottige performance. probier den source doch mal aus, dann wirst du es merken.


----------



## Evil-Devil (9. Sep 2010)

Was fällt denn bei dir unter "grottige" Performance? Du hast zwar dort nur 400 GLBegin Aufrufe die an sich auf einen reduziert werden sollten, aber selbst ohne dürften da 60+fps drin sein.


----------



## Anony (9. Sep 2010)

naja bei mir ist das viel mehr eine slideshow. hab da mal eine video hoch geladen:
Download: 1.avi | xup.in

liegt das eventuell an meiner jogl.jar oder jogl.dll?


----------



## Guest2 (9. Sep 2010)

Moin,

erstmal unabhängig vom eigentlichen Quellcode oben, verwendest Du zumindest schon mal eine jogl Version, die sehr alt ist. Inzwischen gibt es jogl1 und jogl2. Die Version, die Du verwendest, liegt zeitlich noch deutlich vor jogl1. Du solltest also vermutlich erstmal auf jogl1 (1.1.1a ist die finale Version) oder jogl2 (aktuelle Version) updaten. Siehe z.B.: jogl1, jogl2.

Des Weiteren ist (zumindest in aktuellen Versionen) das glFlush() unnötig. Außerdem ist ein try/catch Block in der display() nicht wirklich gut. Du solltest dein modulo also so umbauen das keine ArithmeticException mehr geworfen werden kann.

Außerdem ist der Aufruf der einzelnen glVertex/glTexCoord nicht optimal. Allerdings sind das noch so wenige, das sich das nicht auswirken sollte.

Erstmal 1:1 sähe Dein Code in jogl2 dann wohl so aus:


```
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;

import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLCanvas;

import com.jogamp.opengl.util.Animator;


public class Test implements GLEventListener {

    private GL2 gl;

    @Override
    public void init(final GLAutoDrawable drawable) {

        this.gl = drawable.getGL().getGL2();

    }


    @Override
    public void display(final GLAutoDrawable drawable) {

        gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);

        for (int intFor01 = 0; intFor01 < 20; intFor01 += 1)
            for (int intFor02 = 0; intFor02 < 21; intFor02 += 1){

                if ((intFor01 % intFor02 % 3) == 0)
                    gl.glColor3d(0.0, 1.0, 0.0);

                else if ((intFor01 % intFor02 % 3) == 1)
                    gl.glColor3d(1.0, 0.0, 0.0);

                else if ((intFor01 % intFor02 % 3) == 2)
                    gl.glColor3d(0.0, 0.0, 1.0);

                gl.glBegin(GL2.GL_QUADS);

                gl.glTexCoord2i(0, 0);
                gl.glVertex3i(intFor01 * 32, intFor02 * 32 - 32, 0);
                gl.glTexCoord2i(0, 1);
                gl.glVertex3i(intFor01 * 32 + 32, intFor02 * 32 - 32, 0);
                gl.glTexCoord2i(1, 0);
                gl.glVertex3i(intFor01 * 32 + 32, intFor02 * 32, 0);
                gl.glTexCoord2i(1, 1);
                gl.glVertex3i(intFor01 * 32, intFor02 * 32, 0);

                gl.glEnd();
            }

    }


    @Override
    public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {

        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glOrtho(0.0, 800.0, 600.0, 0.0, 0.0, 128.0);

        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glLoadIdentity();


    }


    @Override
    public void dispose(final GLAutoDrawable arg0) {

    }


    public static void main(final String[] args) throws IOException {

        final Test base = new Test();
        final Frame frame = new Frame();
        final GLCanvas canvas = new GLCanvas();
        final Animator animator = new Animator(canvas);

        canvas.addGLEventListener(base);
        frame.add(canvas);
        frame.setSize(800, 600);
        frame.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(final WindowEvent e) {

                new Thread(new Runnable() {
                    public void run() {

                        animator.stop();
                        System.exit(0);

                    }

                }).start();
            }
        });

        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        animator.start();

    }

}
```

Gruß,
Fancy


----------



## Anony (9. Sep 2010)

danke, das hat mir sehr geholfen.

bin vorhin schonmal auf die idee gekommen jogl1 von deren homepage zu benutzen und es hat dann auch geklappt. mit deiner hilfe werd ich das heute nacht mal auf jogl2 umbauen - aber jetzt erstmal los ein bisschen sport machen.

gute nacht - anony


----------



## Guest2 (9. Sep 2010)

Dann mach auch direkt aus Zeile 33:


```
for (int intFor02 = 1; intFor02 < 21; intFor02 += 1){
```

(Hab oben vergessen den Startindex anzupassen, damit die AE nicht mehr geworfen wird)

Gruß,
Fancy


----------



## Anony (9. Sep 2010)

das ist blos für die anwendung als test gewesen.

in meiner wirklichen anwendung dient das try...catch dem abfangen einer IndexOutOfBound exception da ich da nen 2 dimensionales array hab - wie auch immer, ich mach mich jetzt mal an jogl2


----------



## Guest2 (10. Sep 2010)

Auch da solltest Du dann deine Indizes so wählen, dass keine IndexOutOfBound geworfen werden kann. Exceptions sind dafür da um "wirkliche Ausnahmen/Fehler" abzufangen, z.B. weil eine Datei nicht geschrieben werden konnte. Den Index deines Arrays kannst Du aber selbst bestimmen, da sollte kein try/catch notwendig sein.

Gruß,
Fancy


----------



## Anony (10. Sep 2010)

ich werde mal schaun, wie ich die exception da raus bekomme. eine frage hätt ich da aber noch. weis von euch jemand eventuell warum das beim scrollen teilweise so ruckelt?


```
import java.awt.Point;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLCanvas;
import javax.swing.JFrame;

import com.jogamp.opengl.util.FPSAnimator;

public class classTest extends JFrame {
    public GLCanvas glCanvasHandle = null;
    public FPSAnimator fpsAnimatorHandle = null;
    
    class classTile {
        public int intType = 0;
        
        public int intX = 0;
        public int intY = 0;
    }
    
    public static void main(String[] args) {
        new classTest();
    }
    
    public classTest() {
        this.setSize(800, 600);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        this.setVisible(true);
        
        this.glCanvasHandle = new GLCanvas();
        
        this.glCanvasHandle.addGLEventListener(new GLEventListener() {
            private GL2 glHandle;
            
            public classTile[][] arrArrTiles = null;
            
            public long longTimeCurrent = 0;
            public long longTimeDifference = 0;
            
            public Point pointCameraLeft = new Point(0, 0);
            public Point pointCameraRight = new Point(800, 600);
            
            public void init(GLAutoDrawable arg0) {
                this.glHandle = arg0.getGL().getGL2();
                
                this.arrArrTiles = new classTile[100][100];
                
                for (int intFor01 = 0; intFor01 < this.arrArrTiles.length; intFor01 += 1) {
                    for (int intFor02 = 0; intFor02 < this.arrArrTiles[intFor01].length; intFor02 += 1) {
                        this.arrArrTiles[intFor01][intFor02] = new classTile();
                        
                        this.arrArrTiles[intFor01][intFor02].intType = 1;
                        
                        this.arrArrTiles[intFor01][intFor02].intX = intFor01;
                        this.arrArrTiles[intFor01][intFor02].intY = intFor02;
                        
                        if (Math.floor(Math.random() * 100.0) < 10.0) {
                            this.arrArrTiles[intFor01][intFor02].intType = 0;
                        }
                    }
                }
                
                long longTimeCurrent = System.nanoTime();
                
                this.longTimeDifference = longTimeCurrent - this.longTimeCurrent;
                this.longTimeCurrent = longTimeCurrent;
            }
            
            public void display(GLAutoDrawable arg0) {
                long longTimeCurrent = System.nanoTime();
                
                this.longTimeDifference = longTimeCurrent - this.longTimeCurrent;
                this.longTimeCurrent = longTimeCurrent;
                
                int intMovement = (int) (0.5 * this.longTimeDifference / 1000000);
                
                this.pointCameraLeft.y += intMovement;
                this.pointCameraRight.y += intMovement;
                this.pointCameraLeft.x += intMovement;
                this.pointCameraRight.x += intMovement;
                
                this.glHandle.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
                
                this.glHandle.glBegin(GL2.GL_QUADS);
                
                int intLeftX = (int) Math.floor(this.pointCameraLeft.x / 48);
                int intLeftY = (int) Math.floor(this.pointCameraLeft.y / 48);
                int intRightX = (int) Math.floor(this.pointCameraRight.x / 48) + 1; // Math.ceil mag hier
                int intRightY = (int) Math.floor(this.pointCameraRight.y / 48) + 1; // irgentwie nicht.
                
                for (int intFor01 = intLeftX; intFor01 < intRightX; intFor01 += 1) {
                    for (int intFor02 = intLeftY; intFor02 < intRightY; intFor02 += 1) {
                        try {
                            classTile classTileCurrent = this.arrArrTiles[intFor01][intFor02];
                            
                            if (classTileCurrent.intType == 0) {
                                this.glHandle.glColor3d(0.0, 1.0, 0.0);
                                
                            } else if (classTileCurrent.intType == 1) {
                                this.glHandle.glColor3d(1.0, 0.0, 0.0);
                                
                            }
                            
                            int intX = ((intFor01 - intLeftX) * 48) - (this.pointCameraLeft.x % 48);
                            int intY = ((intFor02 - intLeftY) * 48) - (this.pointCameraLeft.y % 48);
                            
                            this.glHandle.glTexCoord2i(1, 1); this.glHandle.glVertex3i(intX, intY, 0);
                            this.glHandle.glTexCoord2i(0, 1); this.glHandle.glVertex3i(intX + 48, intY, 0);
                            this.glHandle.glTexCoord2i(0, 0); this.glHandle.glVertex3i(intX + 48, intY + 48, 0);
                            this.glHandle.glTexCoord2i(1, 0); this.glHandle.glVertex3i(intX, intY + 48, 0);
                        } catch (Exception e) {
                        }
                    }
                }
                
                this.glHandle.glEnd();
            }
            
            public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3, int arg4) {
                this.glHandle.glEnable(GL2.GL_DEPTH_TEST);
                
                this.glHandle.glMatrixMode(GL2.GL_PROJECTION);
                this.glHandle.glLoadIdentity();
                this.glHandle.glOrtho(0.0, 800.0, 600.0, 0.0, 0.0, 16.0);
                
                this.glHandle.glMatrixMode(GL2.GL_MODELVIEW);
                this.glHandle.glLoadIdentity();
            }
            
            public void dispose(final GLAutoDrawable arg0) {
            }
        });
        
        this.add(this.glCanvasHandle);
        
        this.fpsAnimatorHandle = new FPSAnimator(this.glCanvasHandle, 60);
        
        this.fpsAnimatorHandle.setRunAsFastAsPossible(false);
        
        this.fpsAnimatorHandle.start();
        
        this.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                new Thread(new Runnable() {
                    public void run() {
                        classTest.this.fpsAnimatorHandle.stop();
                        
                        System.exit(0);
                    }
                }).start();
            }
        });
        
        this.setVisible(true);
    }
}
```

danke - anony


----------



## Guest2 (10. Sep 2010)

Das hat eine ganze Reihe von Gründen. Im Allgemeinen ist eine wirklich gleichmäßige lineare Bewegung auch erstmal nicht so trivial, wie man das annehmen könnte.

In Deinem Code ist das hauptsächliche Problem erstmal, das Du den FPSAnimator auf 60 FPS festnagelst. Gleichzeitig ist vermutlich das VSync an und Dein Monitor wird ebenfalls mit 60 Herz angesprochen. Wenn das Timing jetzt schlecht läuft, will jogl in genau dem Moment ein neues Bild zeichnen, an dem der VSync gerade vorbei ist. Schlimmstenfalls muss dann ein komplettes Bild übersprungen werden. Setzt Du den FPSAnimator hingegen auf z.B. 120, wird das Ruckeln schon deutlich besser. Noch besser und einfacher ist es allerdings, den normalen Animator zu nutzen und diesen einfach gegen das VSync laufen zu lassen. (evtl. gl.setSwapInterval(1) zur Aktivierung des Vsync))

Um das Problem weiter zu kaschieren, bietet sich auch z.B. FSAA an, dann werden die Ränder etwas gleichmäßiger und Mikroruckler etwas abgedämpft. (capabilities.setNumSamples(2) und 
capabilities.setSampleBuffers(true))

Des Weiteren ist die Genauigkeit von System.nanoTime() leider nicht so hoch, wie man sich das wünschen würde. Das ist auch schlicht ein Hartwareproblem, da es auf dem Mainboard nichts gibt, das eine annähernd ausreichende Genauigkeit aufweisen würde. Wenn die Grafikkarte halbwegs aktuell ist, bietet sich diese als Abhilfe, da deren interner Timer wesentlich genauer ist. Bei jogl muss man etwas tricksen, um da ran zu kommen, aber es geht.

Baut man Deinen Code dann noch ein wenig um, dann kommt das dabei raus:


```
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;

import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.GLBuffers;


public class Test2 implements GLEventListener {

    private static final int     GL_TIMESTAMP = 0x8E28;

    private static final float[] QUAD_XY      = { -0.5f, -0.5f, +0.5f, -0.5f, +0.5f, +0.5f, -0.5f, +0.5f };
    private static final float[] QUAD_ST      = { 0f, 0f, 1f, 0f, 1f, 1f, 0f, 1f };

    private final FloatBuffer    vaXY         = GLBuffers.newDirectFloatBuffer(QUAD_XY);
    private final FloatBuffer    vaST         = GLBuffers.newDirectFloatBuffer(QUAD_ST);

    private final int            type[][]     = new int[100][100];

    private float                posX         = 0;
    private float                posY         = 0;

    final IntBuffer              timeBuffer   = GLBuffers.newDirectIntBuffer(1);
    private long                 oldTime;

    private GL2                  gl;


    public Test2() {

        for (int i = 0; i < type.length; i++)
            for (int j = 0; j < type[i].length; j++)
                type[i][j] = (Math.floor(Math.random() * 100.0) < 10.0) ? 0 : 1;

    }


    @Override
    public void init(final GLAutoDrawable drawable) {

        gl = drawable.getGL().getGL2();

        gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST);

        gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY);

        gl.setSwapInterval(1);

    }


    @Override
    public void display(final GLAutoDrawable drawable) {

        gl.glGetIntegerv(GL_TIMESTAMP, timeBuffer);

        final long currentTime = timeBuffer.get(0) & 0xffffffffL;
        long delta = currentTime - oldTime;

        if (currentTime < oldTime)
            delta += 0xffffffffL;

        oldTime = currentTime;


        final double step = delta / 320000000.0;

        posX -= step;
        posY += step;

        gl.glClear(GL2.GL_COLOR_BUFFER_BIT);
        gl.glLoadIdentity();
        gl.glTranslatef(-1.05f, 1f, 0);
        gl.glScalef(0.1f, 0.1f, 1);

        gl.glTranslatef(posX, posY, 0);

        for (int i = 0; i < type.length; i++) {

            gl.glPushMatrix();
            gl.glTranslatef(0, -i, 0);

            for (int j = 0; j < type[i].length; j++) {

                gl.glTranslatef(1, 0, 0);

                if (type[i][j] == 0)
                    gl.glColor3f(0.0f, 1.0f, 0.0f);

                else
                    gl.glColor3f(1.0f, 0.0f, 0.0f);

                gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, vaST);
                gl.glVertexPointer(2, GL2.GL_FLOAT, 0, vaXY);
                gl.glDrawArrays(GL2.GL_QUADS, 0, vaXY.capacity() / 2);

            }

            gl.glPopMatrix();

        }

    }


    @Override
    public void reshape(final GLAutoDrawable drawable, final int x, final int y, int width, final int height) {

        if (width <= 0)
            width = 1;

        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glOrthof(-1, +1, -((float) height / (float) width), +((float) height / (float) width), 0, 1);
        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glLoadIdentity();

    }


    @Override
    public void dispose(final GLAutoDrawable arg0) {

    }


    public static void main(final String[] args) throws IOException {

        final Test2 base = new Test2();
        final Frame frame = new Frame();
        final GLCapabilities capabilities = new GLCapabilities(GLProfile.get(GLProfile.GL2));

        capabilities.setNumSamples(2);
        capabilities.setSampleBuffers(true);

        final GLCanvas canvas = new GLCanvas(capabilities);
        final Animator animator = new Animator(canvas);

        canvas.addGLEventListener(base);
        frame.add(canvas);
        frame.setSize(600, 600);
        frame.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(final WindowEvent e) {

                new Thread(new Runnable() {
                    public void run() {

                        animator.stop();
                        System.exit(0);

                    }

                }).start();
            }
        });

        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        animator.start();

    }

}
```

(Das ist immer noch nicht die optimale Lösung, aber ich vermute Du wirst so schon ein wenig daran knabbern müssen, ehe Du den komplett verstehst. Bei Fragen einfach raus damit. )

Gruß,
Fancy


----------



## Anony (10. Sep 2010)

ach du heiligs blechle, was hast du denn da gemacht. step ist im übrigen bei mir immer 0 (delta auch), weshalb sich das ganze noch nicht bewegt^^

aber du hast recht, ich hab da jetzt erst mal dran zu knabbern - ich meld mich wieder sobald fragen aufkommen


----------



## Anony (10. Sep 2010)

da kommt mir schon die erste frage auf. wo bring ich denn das setSwapInterval unter? wenn ich das in die init fuktion packe, wird die framerate nicht limitiert.


----------



## Anony (10. Sep 2010)

ah ok, jetzt hab ich gesehen dass du das setSwapInterval in den init gepackt hast. ich hatte es vorher - anders als erwähnt - im reshape und habs jetzt in den init gepackt - jetzt funktioniert der limiter. sorry, ist schon spät^^

dein testcode läuft bei mir aber nicht wirklich performant - bekomm da nur 20fps hin oder so - und wirklich verstehen tu ich ihn auch nicht ...


----------



## Guest2 (12. Sep 2010)

Wenn das delta immer 0 ist, kann wahrscheinlich der Timer der Grafikkarte nicht gelesen werden. In dem Fall bricht die erste Optimierung weg und Du must wieder auf System.nanoTime() zurück. Wenn Deine Grafikkarte das mit dem Timer nicht unterstützt, unterstützt sie vermutlich auch FSAA nicht richtig. Dadurch wird das dann so langsam. Ausschalten kannst Du das, indem Du die Zeilen 145 und 146 entfernst. Ist das zufällig ein Apple oder ne onboard Lösung?

Das Ganze ist aber auch nur eine Zwischenlösung. In Deinem Code oben zeichnest Du 10000 Felder, indem Du jeweils 4 Eckpunkte mit glTexCoord und glVertex definierst. Das sind schon 80000 OpenGL Aufrufe pro Frame, 4.8 Millionen pro Sekunde. In meinem Code oben wird ein Quadrat in einem Array definiert. Nur dieses eine Quadrat wird 10000-mal gezeichnet. Und zwar immer um den 0/0 Punkt. Mit glTranslate wird das Koordinatensystem so verschoben, dass eine Fläche entsteht, die so aussieht wie in Deinem Beispiel. Die eigentliche Bewegung entsteht dann mit einem zusätzlichem glTranslate (Zeile 88). 

Wenn Du das Prinzip dahinter nämlich verstanden hast, wird es interessant, da Du dann auch Deine Fläche nicht mehr aus einzelnen Quadraten aufbauen musst, sondern das gesamte Feld per Array an OpenGL übertragen kannst. Das spart Dir dann 79997 OpenGL Aufrufe ein.

Da Du auch Texturkoordinaten definierst, vermute ich, dass Du an einem "tiles based 2D side scroller" baust. Dann kannst Du Deine Gittergeometrie nämlich statisch machen, die 2D Bewegungen mit glTranslate realisieren und die angezeigten tiles über dynamisch berechnete Texturkoordinaten bestimmen. Dann hättest Du in Deiner render loop nur noch 6 OpenGL Aufrufe.

Das Gemeine daran ist halt nur, ums einfach machen zu können, muss man erstmal verstehen. 


Gruß,
Fancy


----------



## Guest2 (12. Sep 2010)

Nachtrag:

Du kannst auch mal einen Blick auf den Quelltext in diesem post werfen. Das Prinzip da ist ähnlich, es gibt ein festes Gitter, auf dem ein Text aus einzelnen tiles entsteht. Die Auswahl, welches tiles wo dargestellt wird, wird über die Texturkoordinaten bestimmt.

Bei Dir wären das dann nur eben keine Buchstaben, sondern normale Grafiken. Die Bewegung des gesamten Gitters (rechts / links / oben / unten) würde dann per glTranslate ablaufen.

Gruß,
Fancy


----------



## Anony (12. Sep 2010)

also 100*100 felder gleichzeitig zeichne ich ja auch nicht - nur die sichtbaren 

so ganz verstanden hab ich das prinzip noch nicht. ich werde erstmal so fortfahren, die sichtbaren tiles zu zeichnen und eventuell später - falls es die performance erfordert - auf den von dir beschriebenen weg umsteigen. du hast mir auf jeden fall sehr geholfen. danke nochmal dafür.

zu meinem vorhaben: es wird eine art rts - wegfindung steht schon


----------



## Anony (12. Sep 2010)

ich hätte da noch eine frage.

ich will jetzt mit glPoints punkte zeichnen. funktioniert eigentlich auch ohne probleme, nur wenn ich außerhalb des mit glOrtho bestimmten bereichs zeichne, macht er garnix.

konkret: 800x600 - wenn ich einen point mit size 100 bei x:810 y:400 zeichnen will, macht er garnix.

gibts dafür irgend ne option das zu ändern oder muss ich auch hier wieder quads nehmen?


----------



## Guest2 (12. Sep 2010)

Imho geht das bei Punkten nicht anders (da kann ich mich aber auch irren, Punkte sind sehr legacy).

Eigentlich ist alles außer Dreiecken böse. Auch das Quad wird intern in 2 Dreiecke zerlegt. Grundsätzlich sollte man also alles aus Dreiecken zusammenbauen. Wenn man es sich einfach machen will, gehen aber auch Quads. Wenn Du also einen Punkt mit einer Größe von 100 haben willst, solltest Du z.B. ein Quad mit einer Größe von 100x100 nehmen und eine Textur drüberlegen.

Gruß,
Fancy


----------



## Anony (12. Sep 2010)

okay, dann nehm ich erstmal wieder quads - danke


----------

