Java OpenGL ist eine Wrapper-Bibliothek, die die Verwendung der plattformübergreifenden Standard-Grafik-API OpenGL in Java ermöglicht. Der Artikel erklärt den Einsatz der wichtigsten Funktionen von JOGL.
Seit dem Erscheinen der Java-SE-6[1]-Version sind Java 2D[2] und JOGL[3] interoperabel. Dadurch kann JOGL Swing-Komponenten über das OpenGL-Rendering legen, OpenGL-3D-Grafiken über das Java-2D-Rendering zeichnen, Java-2D-Grafiken über das 3D-OpenGL-Rendering zeichnen und so weiter.
JOGL wird momentan von der Game Technology Group entwickelt, die zu Sun Microsystems gehört. Die Programmbibliothek gilt als Referenzimplementierung für JSR-231 (Java Bindings for OpenGL).
![]() Der Screenshot zeigt das Rendering mit OpenGL unter der Verwendung von JOGL. Er liefert ein Beispiel für Lichtbrechungs- und Spiegelungseffekte. |
Das Design von JOGL
In JOGL erfolgt der Zugriff auf die Basis-OpenGL-C-API über JNI-Aufrufe (Java Native Interface). Das zugrunde liegende System muss also OpenGL unterstützen, damit JOGL funktioniert. JOGL unterscheidet sich von so manch anderen Java-OpenGL-Wrapper-Bibliotheken: Es verwendet kaum die prozedurale OpenGL-API und arbeitet mit nur wenigen Wrapperklassen. Es versucht also nicht, die OpenGL-Funktionalität auf das objektorientierte Programmierparadigma abzubilden.
Den JOGL-Code erstellen die OpenGL-C-Header-Dateien großteils automatisch. Dafür kommt das Konvertierungstool Gluegen zum Einsatz. Es wurde eigens zur Vereinfachung der Entwicklung von JOGL programmiert. Diese Design-Entscheidung hat Vor- und Nachteile.
OpenGL ist eher eine Zustandsmaschine und prozedural angelegt. Das passt eigentlich nicht zur typischen Verfahrensweise des Programmierens unter Java. Viele Programmierer finden das sehr lästig. Das unkomplizierte Mapping der OpenGL-C-API auf Java-Methoden erleichtert aber die Konvertierung bestehender C-Anwendungen und des Beispielcodes enorm. Durch die dünne Abstraktionsschicht von JOGL funktioniert die Laufzeitausführung sehr effizient. JOGL ist jedoch viel schwieriger zu programmieren als Bibliotheken mit höherer Abstraktion, beispielsweise Java 3D[4]. Da der größte Teil des Codes automatisch erstellt wird, können Veränderungen an OpenGL auch rasch zu JOGL hinzugefügt werden. Um JOGL-Code ausführen zu können, benötigt der Entwickler (mindestens) Sun J2SDK 1.4.2 und die JOGL-Binärdateien[5]. Das Betriebssystem sollte ausgewählt und die Bibliothek dekomprimiert werden. Außerdem muss gewährleistet sein, dass letztere im Java-Klassenpfad enthalten ist.
Damit die JOGL-APIs verwendet werden können, muss man das JOGL-Paket in den Code einbinden. Das funktioniert mit dem folgenden Importbefehl:
import net.java.games.jogl.*;
Anschließend erstellt man ein Fenster, das alle Zeichnungen aufnimmt. In AWT geschieht dies durch den Aufruf des Konstruktors new Frame("Hello World"). Zu diesem Frame/Fenster wird nun ein JOGL GLCanvas oder GLJPanel hinzugefügt, damit JOGL die OpenGL-Bindungen verwenden kann.
Durch eine Factory-Methode lässt sich ein neues GLCanvas oder GLJPanel erstellen. Sobald ein neues Canvas/Panel vorhanden ist, fügt man es zum Frame hinzu. Dadurch rendert der Frame das Canvas/Panel zusammen mit dem Rest des Fensters. Auf diese Weise ist es ganz einfach, OpenGL-Funktionen zu einer bestehenden Java-GUI hinzuzufügen.
Der Frame benötigt noch ein paar zusätzliche Parameter, etwa Fenstergröße oder Hintergrundfarbe, und Anweisungen, was geschehen soll, wenn der Benutzer das Fenster schließt. Im aktuellen Beispiel wird die gesamte Anwendung geschlossen und anschließend nur noch der Frame angewiesen, sich selbst zu rendern und Eingaben des Benutzers anzunehmen:
Damit steht eine einfache Umgebung für das JOGL/OpenGL-Rendering zur Verfügung. Als Nächstes muss das GLCanvas/GLPanel um Ereignis-Handler für bestimmte Ereignisse erweitert werden. Das ermöglicht Reaktionen auf bestimmte Benutzerereignisse, beispielsweise Tastatur- oder Mausbewegungen, und Systemereignisse wie Zeichnen, Rendern oder Zeiteinstellungen.
Bei JOGL und AWT gelten Benutzerhandlungen und Systemanfragen als Ereignisse. Hier geht es in erster Linie um die von OpenGL geschaffenen Ereignisse im Zusammenhang mit Initialisierung, Umformung und Anzeigefenster. Ein net.java.games.jogl.GLEventListener überwacht diese Ereignisse. Ebenso lassen sich Ereignisse der Tastatur, Maustasten und Mausbewegungen überwachen, alle von java.awt. Das sollte für einfache Benutzerinteraktionen genügen.
Der nächste Schritt besteht im Erstellen einer neuen Klasse namens JoglEventListener. Sie implementiert alle Methoden, die für die vier Ereignisse relevant sind. Das verknüpfte GLCanvas wird an den Konstruktor des Ereignis-Listeners übergeben. Ansonsten kann das Ereignis Anzeigen/Aktualisieren nicht richtig verarbeitet werden.
Ist der GLEventListener implementiert, werden vier Ereignisse beobachtet: init(), display(), reshape() und displayChanged().
Das Ereignis init() ist eine Initialisierungsfunktion. OpenGL/JOGL ruft sie auf, wenn beim Starten des Programms die Grafikinformationen organisiert werden. In der Regel genügen globale Einstellungen. Die GL-Instanz wird mithilfe der Programmoptionen initialisiert.
Mit java.awt.Component.paint() lässt sich display() vergleichen. Jedes Mal, wenn die Leinwand neu gezeichnet werden muss, erfolgt ein Aufruf. Der unten aufgeführte Code zeichnet die Objekte (Dreieck, Diamant, Rechteck) auf das spezifizierte GLDrawable-Canvas.
Das Ereignis reshape() skaliert das Anzeigefenster neu. In vorliegendem Fall muss festgelegt werden, wie Canvas auf Änderungen der Fenstergröße durch den Benutzer reagieren soll. Es gilt hier, die Größe des Darstellungsfelds anzupassen.
Die letzte grundlegende Methode in JOGL ist displayChanged(). In manchen Fällen ändert sich der Anzeigemodus bei laufendem Programm. Die Methode ist zwar nicht wirklich in JOGL implementiert, aber vielleicht wird das eines Tages der Fall sein. Daher sollte man die JOGL-JavaDocs vor der Verwendung überprüfen.
Erwägungen zum Multi-Threading
Laut JOGL-Handbuch[6] verwenden Bibliotheken wie das OpenGL Utility Toolkit (GLUT) zur Ereignisverarbeitung ein Modell mit nur einem Thread. Bei einer Callback-Registrierung wird die Callback-Funktion folglich von jenem Thread angerufen, auf dem auch der GLUT-Ereignisprozessor lief.
AWT und JOGL verfolgen einen Multi-Threading-Ansatz. Das heißt, die AWT- und JOGL-Bibliotheken erzeugen bei mehreren Ereignissen auch mehrere Threads: einen Thread für Maus- und Tastaturereignisse, einen Thread für Systemereignisse, einen Thread für Anzeige- sowie Rendering-Ereignisse und so weiter. Aus diesem Grund muss gewährleistet sein, dass das Programm gemeinsame Daten zeitgleich verarbeitet.
Weitere Informationen zu OpenGL:
Nach der Erstellung eines GLCanvas oder GLJPanel und der OpenGL-Klassen lässt sich mit OpenGL genauso verfahren wie mit C/C++. Man erhält ein OpenGL-Kontextobjekt in den OpenGL-Methoden init(), display() und so weiter. Damit lassen sich dann die API-Befehle aufrufen. (OpenGL-Programmierung und Echtzeit-3D-Grafiken werden in diesem Artikel nicht berücksichtigt.)
Beispielprojekte mit JOGL, die sehr OpenGL-lastig sind, finden sich auf java.net[7]. Die OpenGL-Webseite[8] bietet ebenfalls zahlreiche Informationen für ein besseres Verständnis der Funktionsweise.
URLs in diesem Artikel:
[1] = http:/
[2] = http:/
[3] = https:/
[4] = http:/
[5] = https:/
[6] = https:/
[7] = https:/
[8] = http:/
