Lwjgl oder Jogl

Hi Leute.
Da ich mit Freunden seit einer gewissen Zeit ein größeres Projekt plane, will ich von Java2D (bye bye :() wegkommen, und opengl lernen. Ich beschäftige mich seit ein paar Wochen auch mit Lwjgl, habe natürlich nebenbei einiges dazu gelesen und erfahren, das die ganzen Tutorials die org.lwjgl.opengl.GL11 und GL12 massenhaft veraltetes Zeugs beibringen. In Opengl 3+ wurde ja quasi alles komplett anders, und man soll ogl 1 und 2 einfach nicht mehr nutzen.

Es gibt ja auch noch die Jogl implementierung. Meines Wissens nach hängt die aber sehr weit zurück, sodass damit eigentlich nur opengl 1 und 2 programmierung möglich wäre, oder stimmt das nicht?
Lwjgl aber hat die Klassen GL33 zum beispiel, oder sogar GL44. Aber als ich versucht hab aus ein paar tutorials ein bisschen code nachzubauen, viel mir auf das einige funktionen in der Lwjgl (Schnittstelle?) lib einfach fehlen… also opengl 3+ ist dort irgendwie nicht komplett.

Jetzt stellt sich mir die Frage: Brauch ich das überhaupt? Es ist ein 2D Projekt, es soll aber etwas umfangreicher werden daher kein Java2D. Aber braucht man Opengl 3+, oder ist es in Ordnung für 2d auch einfach weiterhin opengl 1 und 2 zu verwenden? Wenn ja, kann ich ja einfach Jogl verwenden, was dann eben wirklich NUR eine opengl schnittstelle ist. (oder nicht? ^^)

Was würdet ihr sagen? Ausserdem, habe ich bisher kein einziges Lwjgl Tutorial zu Opengl 3+ gefunden. Klar, OpenGL kann man mehr oder weniger plattformübergreifend erklären / lehren, aber das nur als Bemerkung das es irgendwie keiner macht. Nur auf der Homepage von denen findet man etwas Code zum Thema “OpenGL 3+”, aber dort werden zB auch GL11 und GL12 Methoden und Werte verwendet… außerdem sind das Keine wirklichen Erklärungen sondern hingeklatschter Code.

Opengl 3+ Open “Books” findet man ja viele, aber wie gesagt… eben nichts für java spezifisches. Das ist nich mein Hauptproblem, das zu übertragen würde ich schon hinbekommen… aber naja; erstens scheint lwjgl in dieser Hinsicht eben nicht Komplett zu sein und… brauch ich das überhaupt?

Was würdet ihr für Open Books für das empfehlen, was ihr mir empfehlen würdet?

Vielen Dank!

Ja OpenGl … da werden Erinnerungen wach und zwar keine guten :D. Wollte es mal für Spieleentwicklung lernen, aber weit bin ich nicht gekommen - letztendlich arbeite ich mich in Unity ein. Genau wie du habe ich damals auch viel ausschau nach Tutorials im Netz gehalten und eines hatte ich noch in den Bookmarks. Ich weiß ehrlich gesagt garnicht, welche OpenGL-Version da erklärt wird - aber da du eh noch unentschlossen scheinst, poste ich trotzdem mal den Link:

http://wiki.delphigl.com/index.php/Tutorial

Ist zwar in Delphi - aber ich denke das kann man trotzdem gut auf Java übertragen.

[QUOTE=mymaksimus]Hi Leute.
Da ich mit Freunden seit einer gewissen Zeit ein größeres Projekt plane, will ich von Java2D (bye bye :() wegkommen, und opengl lernen. Ich beschäftige mich seit ein paar Wochen auch mit Lwjgl, habe natürlich nebenbei einiges dazu gelesen und erfahren, das die ganzen Tutorials die org.lwjgl.opengl.GL11 und GL12 massenhaft veraltetes Zeugs beibringen. In Opengl 3+ wurde ja quasi alles komplett anders, und man soll ogl 1 und 2 einfach nicht mehr nutzen.
[/quote]

Das stimmt so weit im Groben. Aber nebenbei: OpenGL ist insgesamt schon SEHR low-level. Es gibt viele Frameworks für 2D-Spiele. Die bekanntesten sind wohl http://slick.ninjacave.com/ , http://code.google.com/p/playn/ oder GitHub - libgdx/libgdx: Desktop/Android/HTML5/iOS Java game development framework , aber es gibt sicher noch 1000 andere (und eine konkrete Empfehlung kann ich nicht geben - erstens, weil ich sie nicht kenne und aktiv verwendet habe, und zweitens, weil es natürlich davon abhängt, was genau man machen will), die man schnell mit sowas wie java opengl 2d game engine - Google Suche finden sollte. Der Vollständigkeit halber erwähne ich auch nochmal die http://forum.byte-welt.net/threads/4613-Jemge-Open-Source-Game-Engine :wink:
Jedenfalls würde so eine Engine einem i.a. VIEEEL Arbeit abnehmen und VIEEL schneller Erfolgserlebnisse bescheren. Ob man sich, wenn das Fernziel ein richtiges Spiel ist, mit der Frage beschäftiten will, ob die Daten, die man an glTexImage2D übergibt, nun das Format GL_UNSIGNED_SHORT oder vielleicht doch GL_UNSIGNED_INT_2_10_10_10_REV haben, muss aber jeder für sich entscheiden… (das war nur ein Suggestivbeispiel ;))

Es gibt ja auch noch die Jogl implementierung. Meines Wissens nach hängt die aber sehr weit zurück, sodass damit eigentlich nur opengl 1 und 2 programmierung möglich wäre, oder stimmt das nicht?
Lwjgl aber hat die Klassen GL33 zum beispiel, oder sogar GL44. Aber als ich versucht hab aus ein paar tutorials ein bisschen code nachzubauen, viel mir auf das einige funktionen in der Lwjgl (Schnittstelle?) lib einfach fehlen… also opengl 3+ ist dort irgendwie nicht komplett.

JOGL unterstützt auch OpenGL 4.3, und wird auch noch aktiv weiterentwickelt. Die Struktur der Klassen ist etwas anders. Bei LWJGL gibt es die ganzen GLXX-Klassen mit static methods, was … nun … entweder sehr übersichtlich ist… oder genau das Gegenteil :wink: … jedenfalls kann man damit i.a. leichter Programme 1:1 von C nach Java übersetzen. JOGL hat GL-Instanzen mit verschiedenen Versionen und Profiles, was IMHO manchmal etwas „sperrig“ wirkt (weil man diese Instanzen überall hin mitschleifen muss…), aber das ist nur ein subjektiver Eindruck: Auch da unterscheidet sich der größte Teil des Quellcodes zwischen C und Java im wesentlichen dadurch, dass vor den Methodenaufrufen eben noch ein „gl.“ steht (abgesehen von den Sprachspezifika, Buffer statt Pointer etc…)

Jetzt stellt sich mir die Frage: Brauch ich das überhaupt? Es ist ein 2D Projekt, es soll aber etwas umfangreicher werden daher kein Java2D. Aber braucht man Opengl 3+, oder ist es in Ordnung für 2d auch einfach weiterhin opengl 1 und 2 zu verwenden? Wenn ja, kann ich ja einfach Jogl verwenden, was dann eben wirklich NUR eine opengl schnittstelle ist. (oder nicht? ^^)

Das ist die entscheidende Frage - aber die ist eigentlich unabhängig von der Frage, ob es JOGL oder LWJGL ist: Die meisten Neuerungen, die bei OpenGL 3.x dazukamen, beziehen sich eben gerade NICHT auf 2D-Dinge. Im Gegenteil: Die wichtigsten 2D-Funktionen wurden in diesen Versionen „deprecated“. Sie sind zwar noch vorhanden und funktionieren auch noch, aber …ja. Man könnte 2D-Funktionen mit den 3D-Funktionen „emulieren“. Lapidar formuliert: Man erstellt ein großes Rechteck, das den ganzen Bildschirm einnimmt, und rendert das dann schick, mit Texturen und so,… oder verwendet viele kleine Rechteckige, texturierte Objekte als „Sprites“… aber das schreibt man wohl nicht mal einfach so schnell runter. Außer Fancy.

Was würdet ihr sagen? Ausserdem, habe ich bisher kein einziges Lwjgl Tutorial zu Opengl 3+ gefunden. Klar, OpenGL kann man mehr oder weniger plattformübergreifend erklären / lehren, aber das nur als Bemerkung das es irgendwie keiner macht. Nur auf der Homepage von denen findet man etwas Code zum Thema „OpenGL 3+“, aber dort werden zB auch GL11 und GL12 Methoden und Werte verwendet… außerdem sind das Keine wirklichen Erklärungen sondern hingeklatschter Code.

Opengl 3+ Open „Books“ findet man ja viele, aber wie gesagt… eben nichts für java spezifisches. Das ist nich mein Hauptproblem, das zu übertragen würde ich schon hinbekommen… aber naja; erstens scheint lwjgl in dieser Hinsicht eben nicht Komplett zu sein und… brauch ich das überhaupt?

Was würdet ihr für Open Books für das empfehlen, was ihr mir empfehlen würdet?

Ja, das ist etwas schwierig. Es kommt kaum noch jemand damit nach, die ständig neuen OpenGL-Versionen/Features zu dokumentieren. Noch weniger damit, kleine KSKBs dafür zu erstellen. Und NOCH weniger damit, diese KSKBs nach LWJGL und JOGL zu portieren. Man muss sich wohl an das klammern, was für C diesbezüglich veröffentlicht wird - und wenn man diese Sachen schon portiert, dann auch gleich veröffentlichen, damit andere das nicht auch nochmal machen müssen :wink:
Aber noch nebenbei: Nur dass eine GL11-Funktion verwendet wird, heißt nicht, dass der Code „veraltet“ ist - nicht alle GL11-Funktionen sind „deprecated“.

Eine Entscheidung bzgl. JOGL/LWJGL würde ich dir nicht abnehmen. Je nachdem, was man vorhat, kann/sollte man sowieso überlegen, ob man die Teile, die spezifisch für eine dieser beiden Libs sind, nicht „wegabstrahiert“ - aber das wäre natürlich schon der erste Schritt in Richtung einer eigenen Engine, und damit macht man ein bodenloses Fass auf :wink: Die Frage, ob man überhaupt die neuen GL-Funktionen braucht, oder ggf. eine fertige Engine in betracht ziehen sollte, hatte ich ja schon in den Raum gestellt.

Noch die üblichen Links:
http://www.opengl.org/sdk/docs/man/ Die Referenz, nur der Vollständigkeit halber
http://www.arcsynthesis.org/gltut/ Umfangreiches, ziemlich modernes Buch
http://www.opengl-tutorial.org/ Ein modernes Tutorial
Homepage of Norbert Nopper Viele KSKBs - fand ich praktisch

Moin,

LWJGL unterstützt derzeit bis OpenGL 4.4, JOGL aktuell bis OpenGL 4.3. Beachten must Du aber auch die Hartware, auf der das später laufen soll, so unterstützt NVIDIA bis OpenGL 4.4 während AMD/ATI immer noch keinen funktionierenden OpenGL 4.3 Treiber hat. Intel ist seit Ivy bei OpenGL 4.0. So das Du vermutlich sowohl LWJGL als auch JOGL als aktuell genug ansehen kannst.

Ob man JOGL oder LWJGL bevorzugt ist Geschmackssache. Der offensichtlichste Unterschied ist der statische Zugriff auf die OpenGL Funktionen bei LWJGL vs. dem Zugriff über einen OpenGL-Kontext-Object bei JOGL. Ich halte den Ansatz von JOGL für besser. Zu LWJGL gibt es allerdings imho mehr Beispiele.

Wenn man von OpenGL3+ spricht, meint man eigentlich, das keine als deprecated markierten Funktionen genutzt werden. Das heißt aber nicht, das nicht Werte und Funktionen aus älteren OpenGL Versionen verwendet werden dürfen. Z.B. GL_TRUE und GL_FALSE wurden mit OpenGL 1.0 eingeführt und werden vermutlich nie als deprecated markiert. Bei LWJGL werden diese dann eben über GL11 importiert.

Bei aktuellen OpenGL Versionen kann man das Core Profile aktivieren, dann prüft der Grafikkartentreiber bei der Ausführung ob veraltete Funktionen genutzt werden und wirft ggf. einen Fehler.

Der Nachteil von OpenGL3+ ist, das beachtlicher Aufwand getrieben werden muss, ehe das erste Dreieck korrekt dargestellt werden kann. Der Vorteil ist, dass alles, was danach kommt, mit relativ wenig Aufwand möglich ist.

Beispielsweise ist dieses Beispiel relativ nahe an einem Minimal-Beispiel, trotzdem ist es für einen Einstiger vermutlich sehr schwer nachzuvollziehen.

2D oder 3D ist kein allzugroßer Unterschied. Bei 2D ist die dahinterstehende Mathematik ggf. etwas einfacher, aber die notwendigen OpenGL Funktionen bleiben die gleichen.

Viele Grüße
Fancy

Edit: Zu langsam…

LOL :wink:

Meine Aussagen bezogen sich dabei auf sowas wie glDrawPixels, … inwieweit es “üblich” war oder ist, diese bei 2D-Spielen (und in den entsprechenden 2D-game-engines) für die Sprites verwendet wurden, weiß ich aber nicht…

also… ich will bei opengl bleiben. keine anderen libs, ist halt so.
Ich habe ja geschrieben das ich bereits ein bisschen in lwjgl reingeschaut hab, eben mit den sachen wie glBegin() und glEnd()… texturen mit
glBindTexture(id)… solche dinge. (Ot: da hab ich direkt ein tolles problem: Ich hab nen ganz normalen code mit ner stinknormalen game loop… auf dem einen pc alles ok, auf einem anderen dauert die game loop auf einmal im schnitt 300 milli sekunden. wtf?!)
Und letzendlich kann man damit ja schon ein 2d spiel „bauen“. Nur was es jetzt bringt bei 2d grafik irgendwelche shader und wat weiss ich
alles zu verwenden… keine ahnung. (Ot: Kann es sein das Minecraft auch noch mit dem alten Opengl läuft? nur mal so…)
Und wieso sollte ich 2D grafik mit 3d funktionen emulieren? Was bringt denn das bitte für vorteile? :frowning:

Also ich hab jetzt die ganze Zeit nachgedacht und noch ein bisschen recherchiert und eure links angesehen dies das… ich werde wahrscheinlich lwjgl benutzen. Ach wahrscheinlich… ich werde es einfach :stuck_out_tongue:

Nun also die Frage, und ich würde euch bitten das wirklich mal für mich zu entscheiden (mit Argumenten! xD)… opengl 3+, oder veraltete 1, 2 funktionen… ich hab nämlich keinen Plan. Mich schreckt 3+ nicht ab, ich bin eigentlich immer bereit neues / mehr zu lernen, (wenns mir spass macht :D) aber… ich weiß eben nicht ob sich das wirklcih auszahlt.

Vielen Dank euch, hoffentlich sagen noch andere etwas dazu!
(oder auch ihr nochmal ^^)

Hm, ja schon möglich das das irgendwo verwendet wird oder wurde. Spontan hätte ich aber ehr an die von Dir bereits angesprochenen texturierten Rechtecke gedacht. Die haben halt den Vorteil, dass man die zum Programmstart einmalig alle auf der Grafikkarte initialisieren kann und dann innerhalb der Game-Loop nur noch jeweils Position und Animationsphase anpassen muss.

Wenn man Funktionen wie glDrawPixels nutzt, muss man ihmo aufpassen das das nicht schnell zum Softwarerenderer mutiert.

Also ich werde das nicht für Dich entscheiden. :wink:

Aber, unabhängig ob deprecated API oder nicht, wie oben schon angedeutet würde ich die Spielobjekte immer als texturierte Rechtecke darstellen. Zur Laufzeit muss dann Position, ggf. Größe und ggf. Textur/Animationsphase angepasst werden.

Unterschiedlich ist nur die konkrete Umsetzung. Bei der deprecated API wären das eben im wesentlichen Display-Listen und glTranslate. Bei OpenGL3+ VAO, VBO, IBO, UBO, VS, FS,…
Das ist erstmal erschlagend. Konkret aber nicht so schwierig, wenn man es einmal verstanden hat.

Z.B. die Shader, bei OpenGL3+ brauchst Du die zwar zwingend, aber mehr als ein 3-Zeiler wird das wahrscheinlich nicht werden.

Eine Frage ist auch, wie groß die Motivation ist etwas zu lernen, das bereits als veraltet gilt.

Viele Grüße
Fancy

/pushitup

also, was empfiehlt ihr mir jetzt konkret…
Nochmal zusammengefasst:

-ein 2d Projekt
-Opengl

→ Opengl „Alt“, 1 & 2?
→ Opengl „Modern“, 3+ ?

Vielen Dank :stuck_out_tongue:

Wie kommst du denn darauf, dass JOGL veraltet ist? Um mit LWJGL mithalten zu können, hat man (wie ich es in meinem Bekanntenkreis prophezeit hatte) zusammen gelegt und deswegen existieren JOGL, JOAL und JOCL afaik nicht mehr eigenständig als solches. Das Ganze heisst jetzt JogAmp.

http://jogamp.org/

LWJGL ist aber immernoch aktueller und hat den “Vorteil” (das gehört bei Java eindeutig in Anführungszeichen ;)), dass es, wie die Libs die sie anbinden, statisch implementiert wurde, was eigentlich nur deswegen Vorteilhaft ist, wenn man OpenGL C- oder Delphi-Tutorials in Java durcharbeiten will. Das geht zwar mit beiden APIS, wenn man sich nicht allzu ungeschickt anstellt, ist in JOGL aber ein wenig unhandlicher.

Für den Einstieg in GL empfehle ich immer die Neon Helium Tutorials (in deutsch von Joachim Rhode oder im Original, dass gibt sich nichts). NeHe ist zwar (überwiegend) für GL1.x aber Grundlagen bekommt man da allemale mit. Man muss nur im Hinterkopf behalten, dass seit GL2 vieles und in GL3+ noch mal vieles mehr anders ist.

Seit OpenGL 1.2 erfolgen die OpenGL Aufrufe über Funktionszeiger. Die zugehörigen Adressen (und damit die konkreten Implementierungen) können dabei erst zur Laufzeit bestimmt werden. Dabei gilt insbesondere für Windows:

Man kann also hoffen das z.B. glUseProgram und glUseProgram tatsächlich identisch sind, sicher sein kann man sich dessen aber nicht. Deshalb ist es bestenfalls unoptimal glUseProgram als static zu deklarieren. Praktisch fällt das aber nur wenig ins Gewicht, weil der durchschnittliche LWJGL Anwender wohl nur einen Kontext verwendet. (Ich glaube mit der aktuellen LWJGL Version sind mehrere auch gar nicht mehr möglich.)

Ausführlicher gibt es das im OpenGL Wiki unter: https://www.opengl.org/wiki/Load_OpenGL_Functions

Viele Grüße
Fancy

[QUOTE=Fancy]Seit OpenGL 1.2 erfolgen die OpenGL Aufrufe über Funktionszeiger.[/QUOTE]Das meinte ich so nicht. Wo du in C z.B. “glLoadIdentity()” schreibst, kannst du in LWJGL genauso “glLoadIdentity()” schreiben, wenn du entsprechende Klassen statisch importierst. In JOGL kannst du diese Funktionen nur auf ein Objekt anwenden: “gl.glLoadIdentity()”. Soweit ich weiss, kannst (bzw. musst) du in LWJGL (lediglich) einen PBuffer (ist das der Context?) pro Thread haben. Die Klasse Display ist dort nur eine Hilfsklasse, die dir neben anderen Kleinigkeiten recht einfach ein GL-Fenster hinzaubert. Mit LWJGL geht aber viel mehr, so lässt sich mit folgendem z.B. relativ einfach eine GLComponent realisieren.

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.*;

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Set;
import java.util.TreeSet;

import javax.datatypes.utils.IdentityArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Pbuffer;
import org.lwjgl.opengl.PixelFormat;

public class KSKB {
	public static void main(String[] args) {
		JFrame f = new JFrame("Swing LWJGL");
		GLJPanel gljp = new GLJPanel() {
			private static final long serialVersionUID = -38094150939029442L;

			private final float[] bg = new float[4];

			@Override
			protected void initGL() {
				glEnable(GL_TEXTURE_2D);
				glShadeModel(GL_SMOOTH);
				getBackground().getColorComponents(bg);
				glClearColor(bg[0], bg[1], bg[2], bg[3]);
				glClearDepth(1.0);
				glEnable(GL_DEPTH_TEST);
				glDepthFunc(GL_LEQUAL);
				glMatrixMode(GL_PROJECTION);
				glLoadIdentity();
				gluPerspective(45.0f, getWidth() / (float) getHeight(), 0.1f,
						100.0f);
				glMatrixMode(GL_MODELVIEW);
				glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
			}

			@Override
			protected void paintGL() {
				glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
				glLoadIdentity();
				glTranslatef(-1.5f, 0.0f, -6.0f);
				glBegin(GL_TRIANGLES);
				glColor3f(1.0f, 0.0f, 0.0f);
				glVertex3f(0.0f, 1.0f, 0.0f);
				glColor3f(0.0f, 1.0f, 0.0f);
				glVertex3f(-1.0f, -1.0f, 0.0f);
				glColor3f(0.0f, 0.0f, 1.0f);
				glVertex3f(1.0f, -1.0f, 0.0f);
				glEnd();
				glTranslatef(3.0f, 0.0f, 0.0f);
				glColor3f(0.5f, 0.5f, 1.0f);
				glBegin(GL_QUADS);
				glVertex3f(-1.0f, 1.0f, 0.0f);
				glVertex3f(1.0f, 1.0f, 0.0f);
				glVertex3f(1.0f, -1.0f, 0.0f);
				glVertex3f(-1.0f, -1.0f, 0.0f);
				glEnd();
			}
		};
		gljp.setSize(800, 600);
		gljp.setPreferredSize(gljp.getSize());
		gljp.setMaximumSize(gljp.getSize());
		gljp.setMinimumSize(gljp.getSize());
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.add(gljp);
		f.pack();
		f.setVisible(true);
	}
}

class PbufferMap {
	private static final long IDLE_TIMEOUT = 5000;
	private static final long IDLE_TIMEOUT_NANOS = IDLE_TIMEOUT * 1000000;
	private static final ResourceSet REFERENCE = new ResourceSet(null);
	private static final PixelFormat FORMAT = new PixelFormat();
	private static final ThreadSet CACHE = new ThreadSet();
	private static int cnt;

	static boolean aquire(Object ressource) {
		synchronized (CACHE) {
			Thread t = Thread.currentThread();
			ResourceSet r = CACHE.forThread(t);
			if(r == null) {
				r = new ResourceSet(t);
				CACHE.add(r);
			}
			r.add(ressource);
			return r.refresh();
		}
	}

	static void release(Object ressource) {
		synchronized (CACHE) {
			Thread t = Thread.currentThread();
			ResourceSet r = CACHE.forThread(t);
			if(r != null) {
				r.remove(ressource);
			}
		}
	}

	private static final class ThreadSet extends IdentityArrayList<ResourceSet> {
		private static final long serialVersionUID = 8331589906165047839L;

		private Thread scheduler;

		synchronized ResourceSet forThread(Thread t) {
			if(scheduler == null) {
				scheduler = new Thread("Pbuffer Dispose Scheduler " + (cnt++)) {
					private TreeSet<ResourceSet> ressources = new TreeSet<>();

					{
						setDaemon(true);
					}

					@Override
					public void run() {
						while(true) {
							synchronized (this) {
								try {
									wait(IDLE_TIMEOUT);
								} catch(InterruptedException e) {
									break;
								}
							}
							REFERENCE.refresh();
							synchronized (CACHE) {
								ressources.addAll(CACHE);
							}
							Set<ResourceSet> tail = new HashSet<>(ressources.tailSet(REFERENCE, false));
							if(!tail.isEmpty()) {
								for(ResourceSet r : tail) {
									r.destroy();
									ressources.remove(r);
								}
								synchronized (CACHE) {
									CACHE.retainAll(ressources);
									if(CACHE.isEmpty()) {
										break;
									}
								}
							}
						}
						scheduler = null;
					}
				};
				scheduler.start();
			}
			for(ResourceSet r : this) {
				if(r.t == t) {
					return r;
				}
			}
			return null;
		}
	}

	private static final class ResourceSet extends IdentityHashMap<Object, Object> implements Comparable<ResourceSet> {
		private static final long serialVersionUID = -3207232556780437227L;

		private final Thread t;
		private Pbuffer buffer;
		private long nanos;

		private ResourceSet(Thread t) {
			this.t = t;
		}

		void destroy() {
			if(buffer != null) {
				try {
					buffer.destroy();
					buffer = null;
				} catch(Exception e) {
					// dann halt nicht
				}
			}
		}

		void add(Object ressource) {
			if(get(ressource) == null) {
				put(ressource, this);
			}
		}

		boolean refresh() {
			nanos = System.nanoTime();
			if(this != REFERENCE) {
				try {
					glGetString(GL_VENDOR);
					if(buffer != null && !buffer.isCurrent()) {
						buffer.destroy();
						buffer = null;
						return true;
					}
					return false;
				} catch(Throwable e) {
					try {
						if(buffer == null || buffer.isBufferLost()) {
							buffer = new Pbuffer(1, 1, FORMAT, null);
							buffer.makeCurrent();
							return true;
						}
						buffer.makeCurrent();
						return false;
					} catch(LWJGLException ee) {
						throw new RuntimeException("open gl not available");
					}
				}
			}
			nanos -= IDLE_TIMEOUT_NANOS;
			return false;
		}

		@Override
		public int compareTo(ResourceSet o) {
			long n = nanos - o.nanos;
			return (n > 0)? -1 : (n < 0)? 1 : 0;
		}

		@Override
		public String toString() {
			return "" + nanos;
		}
	}
}
class GLJPanel extends JPanel {
    private static final long serialVersionUID = -6189316223432196535L;
 
    private byte[] transBufferByte = new byte[4];
    private ByteBuffer data;
    private BufferedImage img;
    private int fbID = -1, texID = -1;
 
    @Override
    public final void paint(Graphics g) {
        super.paint(g);
    }
 
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        paintGL(g);
    }
 
    protected void paintGL() {
    }
 
    protected void initGL() {
    }
 
    private void paintGL(Graphics g) {
        int w = getWidth();
        int h = getHeight();
        int c = w * h * 4;
        PbufferMap.aquire(this);
        if (data == null || data.capacity() != c) {
            initGL(w, h, c);
        }
        glBindTexture(GL_TEXTURE_2D, 0);
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbID);
        glPushAttrib(GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT);
        glViewport(0, 0, w, h);
        paintGL();
        glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data);
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
        glPopAttrib();
        glFlush();
        int color, p;
        for (; data.position() < c;) {
            p = data.position() / 4;
            data.get(transBufferByte);
            color = ((transBufferByte[3] & 0xFF) << 24)
                    | ((transBufferByte[0] & 0xFF) << 16)
                    | ((transBufferByte[1] & 0xFF) << 8)
                    | (transBufferByte[2] & 0xFF);
            img.setRGB(p % w, h - 1 - p / w, color);
        }
        data.rewind();
        g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
    }
 
    private void initGL(int w, int h, int c) {
        data = ByteBuffer.allocateDirect(c).order(
                ByteOrder.nativeOrder());
        img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        if (fbID > 0) {
            glDeleteTextures(texID);
            glDeleteFramebuffersEXT(fbID);
        }
        fbID = glGenFramebuffersEXT();
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbID);
        texID = glGenTextures();
        glBindTexture(GL_TEXTURE_2D, texID);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA,
                GL_UNSIGNED_BYTE, (ByteBuffer) null);
        glBindTexture(GL_TEXTURE_2D, 0);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
                GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texID, 0);
        int status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
        switch (status) {
        case GL_FRAMEBUFFER_COMPLETE_EXT:
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
            throw new RuntimeException(
                    "FrameBuffer has caused a GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT exception");
        case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
            throw new RuntimeException(
                    "FrameBuffer has caused a GL_FRAMEBUFFER_INCOMPLETE_FORMATS exception");
        case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
            throw new RuntimeException(
                    "FrameBuffer has caused a GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT exception");
        case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
            throw new RuntimeException(
                    "FrameBuffer has caused a GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE exception");
        case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
            throw new RuntimeException(
                    "FrameBuffer has caused a GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER exception");
        case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
            throw new RuntimeException(
                    "FrameBuffer has caused a GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER exception");
        default:
            throw new RuntimeException(
                    "Unexpected reply from glCheckFramebufferStatusEXT: "
                            + status);
        }
        initGL();
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
        PbufferMap.release(this);
    }
}```Die PBufferMap erstellt bei Bedarf PBuffers und entfernt diese wieder, wenn sie einen längeren Zeitraum über nicht verwendet wurden. Den GLJPanel muss man nur erweitern und "paintGL" und "intiGL()" überschreiben. Die einzige Anpassung, die bei Bedarf noch getätigt werden müsste, ist, dass man ExtFrameBuffer2D gegen entsprechende FrameBuffer2D funktionen ersetzt, sofern diese vorhanden sind, das ist afaik erst ab GL3.0 der Fall.

Bei glLoadIdentity() ist das tatsächlich so. Du kannst in C aber z.B. nicht einfach glUseProgram() schreiben, weil diese Funktion zur Compilezeit gar nicht existiert. Was Du tatsächlich schreiben müsstest wäre etwa (~Pseudocode):

// Typdefinition
typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
PFNGLUSEPROGRAMPROC glUseProgram;

// Fenster und OpenGL Kontext erzeugen
CreateWindowW(..);
ChoosePixelFormat(..);
SetPixelFormat(..);
wglCreateContext(..);
wglMakeCurrent(..);

// Erst hier wird glUseProgram auf eine konkrete Implementierung gemappt
glUseProgram = (PFNGLUSEPROGRAMPROC)wglGetProcAddress("glUseProgram");

// und kann jetzt erst verwendet werden
glUseProgram(id);

glUseProgram ist also eine Variable (Funktionszeiger), dessen Inhalt vom jeweiligen OpenGL Kontext abhängt. In JOGL kannst Du z.B. problemlos aus einer Java Anwendung heraus zwei Fenster öffnen, eines mit OpenGL 4.2 Core und eines mit OpenGL 2.1 Legacy. Das geht, weil Du context1.glUseProgram(id) und context2.glUseProgram(id) differenzieren kannst. Bei LWJGL grätscht Dir das static da zwischen die Beine.

Angeblich kann das zukünftige LWJGL 3 mit mehreren OpenGL Kontexten umgehen. Aber erstens soll die API teilweise inkompatibel zum derzeitigen LWJGL 2.X sein und zum anderen wird das mit den static-Funktionen (die sollen bleiben) sicherlich nicht sonderlich schön werden.

Was ein OpenGL Kontext ist, ist imho überall nur sehr schwammig angedeutet. Etwas dazu findet sich z.B. hier: https://www.opengl.org/wiki/OpenGL_Context

Insbesondere:

… erinnert mich an JOGL. :wink:

(Aber wie bereits geschrieben, für die meisten dürfte dieser Unterschied unwichtig sein. Nur steckt hinter der C Variante mehr als ein simples „public static void glUseProgram(int program)“)

Viele Grüße
Fancy

Die größten Änderungen bei Lwjgl 3 spielen sich unter der Haube ab. Die statische Natur wird bleiben, sodass ein Umstieg von 2.x auf 3.x relativ leicht vollzogen werden kann.

Die ArcSynthesis Reihe wurde auch portiert. Ansonsten schau mal in unserer Ressourcen Sammlung nach was es alles an Hilfen gibt. http://lwjgl.org/wiki/index.php?title=Learning_LWJGL
Und natürlich freut sich die Community immer über Hilfe :wink: