Schnelle Pixel

Die Grafikleistung von Computersystemen hat in den letzten Jahren zugelegt wie kaum ein anderer Hardwarebereich. Als eine Folge davon gewinnt die 3D-Bibliothek OpenGL zunehmend an Bedeutung. Eine Einführung in die Programmierung zeigt, wie man OpenGL-Funktionen einsetzt.

In Pocket speichern vorlesen Druckansicht
Lesezeit: 14 Min.
Von
  • Christian Marten
Inhaltsverzeichnis

Neben Microsofts DirektX ist die prozedurale Grafikbibliothek OpenGL die zweite große Schnittstelle zur Grafikhardware eines Computers. Im Gegensatz zu DirektX laufen OpenGL-Programme jedoch nicht nur unter MS Windows, sondern sind zwischen unterschiedlichen Plattformen portabel.

Erkauft wird diese Systemunabhängigkeit durch den Verzicht auf Funktionen, die direkt auf betriebssystemabhängigen Eigenschaften aufsetzen. Allerdings gibt es Hilfsbibliotheken wie GLUT, die genau an dieser Stelle einspringen. GLUT ist auf jeder gängigen Plattform verfügbar und stellt unter anderem eine standardisierte API für Fenster- und Ereignisbehandlung sowie Maus- und Tastaturabfragen bereit.

Mehr Infos

Die Beispielprogramme dieses Kurses sind in ANSI C implementiert und sollten sich unverändert auf jedem System vom Macintosh über den PC bis hin zur Unix-Workstation übersetzen lassen, auf dem eine OpenGL-Implementierung, die OpenGL-Utility-Bibliothek GLU, das OpenGL Utility Toolkit GLUT sowie ein C-Compiler installiert sind. Für Rechner unter MS Windows muss der Compiler-Switch OS_WIN32 definiert sein. Die Listings, die unter Linux und Windows NT ausprobiert wurden, sind über den iX-FTP-Server zu beziehen.

OpenGL bietet im Wesentlichen Primitive zur Ausgabe von Punkten, Linien und Polygonen sowie Funktionen zu ihrer Platzierung im dreidimensionalen Raum. Das tatsächliche Erscheinungsbild der Primitive ist allerdings abhängig von einer ganzen Reihe von Rendering-Parametern wie Beleuchtungs- und Materialeinstellungen, Umgebungseinflüssen wie Rauch und Nebel oder Oberflächenmuster, die sich über Texturen realisieren lassen.

Intern arbeitet OpenGL als eine sogenannte State-Maschine. Dies bedeutet, dass Einstellungen wie die aktuelle Zeichenfarbe, die Blickrichtung des Betrachters oder Beleuchtungsparameter nicht bei jedem Primitiv mit übergeben werden müssen. Spezielle Funktionen erlauben Voreinstellungen, die so lange gültig bleiben und die Ausgabe nachfolgender Zeichenprimitive beeinflussen, bis ein erneuter Aufruf sie ändert.

Der OpenGL-Befehlssatz besteht in der Spezifikation 1.1 aus etwa 150 verschiedenen Funktionen; für viele existieren mehrere Varianten, die sich in Anzahl und Datentyp ihrer Parameter unterscheiden. Die Nomenklatur ist dabei recht simpel: Alle Kernfunktionen beginnen mit dem Präfix gl. Der Suffix einer Funktion gibt Auskunft über Art und Anzahl der erwarteten Parameter. Beispielsweise erwartet glVertex3f() drei Werte vom Typ GLfloat zur Definition eines Punktes im Raum. Die verwandte Funktion glVertex4d() verarbeitet anstelle von Float-Variablen Gleitkommazahlen mit doppelter Genauigkeit (GLdouble). Außerdem erwartet sie als vierten Parameter die homogene Koordinate des Punktes. Nachfolgend wird eine Gruppe von Varianten einer Funktion mit einem * bezeichnet, also beispielsweise glVertex*().

sample1.c, das erste Beispielprogramm, öffnet ein Fenster und zeichnet einen bunten Würfel, der sich über die Cursortasten um zwei Achsen drehen lässt. Die Leertaste schaltet zwischen Linien- und Polygondarstellung um.

Mehr Infos

Listing: SAMPLE1.C

  1   /* Linux/Unix: uebersetzen mit
2 gcc sample1.c -lMesaGLU -lMesaGL -lXext -lX11 -lm -lglut -lXi -lXmu \
3 -B/usr/X11/lib
4 */
5
6 #ifdef OS_WIN32
7 # include <windows.h>
8 #endif
9
10 #include <GL/glut.h>
11
12 GLenum polygonMode=GL_LINE;
13 float rotX=0.0, rotY=0.0;
14
15 static void DrawCube ()
16 {
17 /* Wuerfel aus 2 Quadraten und einem Quadratstreifen zusammensetzen */
18 glBegin (GL_QUADS);
19 glColor3f (0.0, 0.0, 0.0); glVertex3f (0.0, 0.0, 0.0); /* unten */
20 glColor3f (1.0, 0.0, 0.0); glVertex3f (1.0, 0.0, 0.0);
21 glColor3f (1.0, 0.0, 1.0); glVertex3f (1.0, 0.0, 1.0);
22 glColor3f (0.0, 0.0, 1.0); glVertex3f (0.0, 0.0, 1.0);
23
24 glColor3f (0.0, 1.0, 0.0); glVertex3f (0.0, 1.0, 0.0); /* oben */
25 glColor3f (0.0, 1.0, 1.0); glVertex3f (0.0, 1.0, 1.0);
26 glColor3f (1.0, 1.0, 1.0); glVertex3f (1.0, 1.0, 1.0);
27 glColor3f (1.0, 1.0, 0.0); glVertex3f (1.0, 1.0, 0.0);
28 glEnd ();
29
30 glBegin (GL_QUAD_STRIP);
31 glColor3f (0.0, 0.0, 1.0); glVertex3f (0.0, 0.0, 1.0); /* vorn */
32 glColor3f (0.0, 1.0, 1.0); glVertex3f (0.0, 1.0, 1.0);
33 glColor3f (1.0, 0.0, 1.0); glVertex3f (1.0, 0.0, 1.0);
34 glColor3f (1.0, 1.0, 1.0); glVertex3f (1.0, 1.0, 1.0);
35
36 glColor3f (1.0, 0.0, 0.0); glVertex3f (1.0, 0.0, 0.0); /* rechts */
37 glColor3f (1.0, 1.0, 0.0); glVertex3f (1.0, 1.0, 0.0);
38
39 glColor3f (0.0, 0.0, 0.0); glVertex3f (0.0, 0.0, 0.0); /* hinten */
40 glColor3f (0.0, 1.0, 0.0); glVertex3f (0.0, 1.0, 0.0);
41
42 glColor3f (0.0, 0.0, 1.0); glVertex3f (0.0, 0.0, 1.0); /* links */
43 glColor3f (0.0, 1.0, 1.0); glVertex3f (0.0, 1.0, 1.0);
44 glEnd ();
45 }
46
47 static void Init(void)
48 {
49 /* Z-Buffer f. Berechnung verdeckter Flaechen einschalten */
50 glEnable(GL_DEPTH_TEST);
51
52 /* Vorder- u. Rueckseite der Polygone nur als Randlinien darstellen */
53 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
54 }
55
56 static void Reshape(int width, int height)
57 {
58 /* Darstellung auf gesamten Clientbereich des Fensters zulassen */
59 glViewport(0, 0, (GLint)width, (GLint)height);
60
61 /* Projektionsmatix initialisieren auf 60 Grad horizontales */
62 /* Sichtfeld, Verhaeltnis Breite:Hoehe = 1:1, Clipping fuer z<1 */
63 /* und z>200 */
64 glMatrixMode(GL_PROJECTION);
65 glLoadIdentity();
66 /* angle, aspect, near Clip, far Clip */
67 gluPerspective(60.0, 1.0, 1.0, 200.0);
68
69 /* Modelview Matrix wieder zur aktuellen Matrix machen */
70 glMatrixMode(GL_MODELVIEW);
71 }
72
73 static void Key(unsigned char key, int x, int y)
74 {
75 if (key==27)
76 exit(1);
77 if (key==' ') {
78 if (polygonMode==GL_FILL)
79 polygonMode=GL_LINE;
80 else
81 polygonMode=GL_FILL;
82
83 /* Polygondarstellung zw. Outline und Gefuellt umschalten... */
84 glPolygonMode (GL_FRONT_AND_BACK, polygonMode);
85
86 /* ... und Bild erneut rendern */
87 glutPostRedisplay ();
88 }
89 }
90
91 static void SpecialKey(int key, int x, int y)
92 {
93 switch (key) {
94 case GLUT_KEY_UP:
95 rotX -= 5;
96 break;
97 case GLUT_KEY_DOWN:
98 rotX += 5;
99 break;
100 case GLUT_KEY_LEFT:
101 rotY -= 5;
102 break;
103 case GLUT_KEY_RIGHT:
104 rotY += 5;
105 break;
106 default:
107 return;
108 }
109 glutPostRedisplay();
110 }
111
112 static void Display(void)
113 {
114 /* FrameBuffer unf Z-Buffer loeschen */
115 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
116 /* Modelview Matrix initialisieren */
117 glLoadIdentity ();
118
119 /* Modeltransformation ausfuehren... */
120 glTranslatef (0.0, 0.0 ,-3.0); /* Verschiebung um -3 in z-Richtung */
121 glRotatef (rotY, 0.0, 1.0, 0.0); /* Rotation um die Y-Achse */
122 glRotatef (rotX, 1.0, 0.0, 0.0); /* Rotation um die X-Achse */
123 glTranslatef (-0.5, -0.5 , -0.5); /* Verschieb. um -0.5, alle Richt. */
124
125 /* ...und den Wuerfel unter der Modeltransformation zeichnen. */
126 DrawCube ();
127
128 /* Back-Buffer in den Front-Buffer kopieren. */
129 glutSwapBuffers();
130 }
131
132 int main(int argc, char **argv)
133 {
134 glutInit(&argc, argv);
135
136 /* Ausgabefenster definieren */
137 glutInitWindowPosition(0, 0);
138 glutInitWindowSize( 300, 300);
139 /* Renderkontext mit Z-Buffer, Doublebuffer fuer RGB-Modus anfordern.*/
140 glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE);
141
142 if (glutCreateWindow("Sample1") == GL_FALSE)
143 exit(1);
144
145 Init();
146
147 /* Callback Funktionen vereinbaren */
148 glutReshapeFunc(Reshape);
149 glutKeyboardFunc(Key);
150 glutSpecialFunc(SpecialKey);
151 glutDisplayFunc(Display);
152
153 /* Kontrolle an GLUT Eventloop uebergeben */
154 glutMainLoop();
155 }

Das Grundgerüst eines GLUT-basierten Programms ist stets gleich. Die main-Funktion (Zeile 132) initialisiert zunächst die GLUT-Bibliothek (glutInit), legt anschließend Position und Größe des Ausgabefensters (glutWindowSize, glutWindowPosition) sowie Eigenschaften des Rendering-Kontextes wie beispielsweise Double Buffering, Z- und Alpha Channel fest (glutInitDisplayMode), vereinbart Callback-Funktionen für bestimmte Ereignisse und erzeugt das Ausgabefenster (glutCreateWindow), das bei Übergabe der Flusskontrolle an GLUT mittels glutMainLoop schließlich auf dem Bildschirm erscheint.

glutMainLoop nimmt die vom Betriebssystem gesendeten Nachrichten entgegen und ruft die für ein bestimmtes Ereignis zuvor vereinbarte Callback-Funktion auf. Das Beispielprogramm definiert Callbacks für das Neuzeichnen (glutDisplayFunc) sowie für eine Größenänderung des Ausgabefensters (glutReshapeFunc). Weiterhin bestimmen glutKeyboardFunc und glutSpecialFunc Funktionen, die bei Tastaturereignissen aufgerufen werden sollen.

Neben den GLUT-Initialisierungen enthält die main-Funktion einen Aufruf der Funktion Init (Zeile 47), die OpenGL-Parameter für das Rendering voreinstellt. Für dieses erste Programm legt Init lediglich fest, dass OpenGL einen Z-Buffer zur Ermittlung verdeckter Flächen verwenden soll (glEnable (GL_DEPTH_TEST)) und für Polygonprimitive nur die Kanten ausgegeben werden sollen (glPolygonMode). Im Lauf des Kurses wird Init um Beleuchtungs- und Materialeinstellungen erweitert.

Die Funktion Reshape (Zeile 56) wird bei jeder Größenänderung des Ausgabefensters aufgerufen. Sie nimmt Einstellungen für die Projektion der 3D-Szene auf die ‘Leinwand’ des Bildschirms vor. Die beteiligten OpenGL-Funktionen werden im Zusammenhang mit Projektions- und Transformationsmatrizen später näher vorgestellt. Für die ersten Experimente mit OpenGL kann die Reshape-Funktion unverändert in andere Programme übernommen werden.

Key (Zeile 73) und SpecialKey (Zeile 91) behandeln Tastaturereignisse und sorgen dafür, dass sich der Würfel über die Cursortasten um zwei Achsen drehen lässt. Außerdem kann der Anwender über die Leertaste zwischen Drahtgitter und ausgefüllter Darstellung umschalten.

Display (Zeile 112) schließlich wird jedesmal aufgerufen, wenn der Fensterinhalt neu gezeichnet werden muss. Zunächst ist lediglich der Aufruf von DrawCube interessant, der für das Zeichnen des Würfels zuständig ist. Alles Weitere dient der Bewegung des Würfels, die ebenfalls später besprochen wird.

DrawCube (Zeile 15) besteht aus dem Paar glBegin und glEnd sowie einer Reihe von Farb- und Koordinatenangaben, die OpenGL über glVertex* und glColor* mitgeteilt werden. Letztlich erfolgt jede (nicht pixelorientierte) Ausgabe unter OpenGL nach diesem Schema:

glBegin (Primitive);
// Angabe von Koordinaten der Eckpunkte,
// Farben, Normalen, et cetera

glEnd();

Die zehn Ausgabeprimitive von OpenGL: Punkte eines Polygons müssen komplanar, das Polygon selbst konvex sein, damit OpenGL es korrekt ‘rendern’ kann. Die Reihenfolge der Punkte legt den Drehsinn und damit die Vorder- und Rückseite eines Polygons fest (Abb. 1).

Als Primitiv kommt die Angabe einer Konstanten aus Abbildung 1 infrage. Das Beispielprogramm wählt mit GL_QUADS und GL_QUAD_STRIP Vierecke und Viereckstreifen als Ausgabeprimitive aus. Erhielte glBegin den Parameter GL_POINTS, so würden nur die Eckpunkte des Würfels dargestellt.

OpenGL unterscheidet die Vorderseite eines Polygons von seiner Rückseite durch die Reihenfolge, in der das Rendering der Punkte erfolgt. Erscheinen die Eckpunkte gegen den Uhrzeigersinn, wird die Vorderseite dargestellt, anderenfalls die Rückseite. Beispielsweise kann OpenGL für beide Seiten eines Polygons verschiedene Materialeigenschaften verwalten oder eine Seite auf Wunsch überhaupt nicht darstellen (Backface Culling).

Das Aussehen von Linien und Polygonen errechnet OpenGL aus Eigenschaften ihrer Eckpunkte. So kann wie im Beispielprogramm jeder Punkt eines Vierecks eine andere Farbe besitzen. Ein Primitiv bekommt nie als Ganzes eine Farbe zugewiesen. Gehören wie im Beispiel mehrere Punkte unterschiedlicher Farbe zum selben Grafikprimitiv, interpoliert OpenGL die Farben der zwischen den Ecken liegenden Punkte.

Für jeden Punkt legt sample1.c über glColor* die Farbe fest, bevor glVertex3f die x-, y- und z-Koordinate spezifiziert. glVertex* ist sehr flexibel und nimmt je nach Suffix zwei, drei oder vier Koordinaten der Datentypen GLint, GLfloat oder GLdouble sowie Arrays mit Koordinaten als Parameter an. Wird auf die Angabe der homogenen Koordinate verzichtet, nimmt OpenGL diese als 1 an. Fehlt auch die z-Koordinate, wird sie automatisch auf 0 gesetzt.

OpenGL bietet zwei Farbmodi an, zwischen denen der Programmierer bei Erzeugung eines Rendering-Kontextes wählen muss: Color Indexed und RGB. Der erste Modus arbeitet wie ein Desktop von 4 oder 8 Bit Farbtiefe mit einer Palette. Die Grafikbibliothek definiert keine Befehle, um Einfluss auf die Farben der Palette zu nehmen. Diese bestimmt das Betriebssystem. Lediglich der aktuelle Farbindex ist über glIndex*() wählbar.

Über den Aufruf glutInitDisplayMode (...GLUT_RGB...) (Zeile 140) wählt das Beispielprogramm den für die meisten Anwendungen besser geeigneten RGB-Modus, der jede Farbe aus den drei Grundfarben Rot, Grün und Blau zusammenmischt. Pro Grundfarbe erwartet OpenGL einen Wert zwischen 0.0 und 1.0, der festlegt, mit welcher Intensität sie in die Mischung eingeht. Ein Wert von 1.0 bedeutet die maximal mögliche Intensität, während eine Grundfarbe mit dem Wert von 0.0 komplett entfällt.

Die drei Achsen des räumlichen Koordinatensystems dienen als Farbachsen, denen jeweils logisch eine Grundfarbe zugeordnet ist. Je größer der Abstand eines auf einer Achse liegenden Punktes zum Ursprung ist, desto größer die Intensität der korrespondierenden Grundfarbe. Da der vom Programm gezeichnete Würfel der Einheitswürfel ist (Kantenlänge = eins) und die Koordinaten seiner Eckpunkte gleichzeitig als deren Farbwerte dienen, haben die Eckpunkte Farben maximaler Intensität. Die Eckpunkte auf den drei Achsen entsprechen Schwarz beziehungsweise den drei Grundfarben, die übrigen Eckpunkte den Mischfarben Gelb, Violett, Türkis und Weiß.

OpenGL erwartet die Angabe von Koordinaten in einem rechtshändigen karthesischen Koordinatensystem. Wenn man die rechte Hand Richtung Monitor ausstreckt, den Daumen (x-Achse) den unteren Rand des Bildschirms sowie den Zeigefinger (y-Achse) den linken Rand entlang und den Mittelfinger (z-Achse) auf die eigene Schulter zeigen lässt, dann deuten besagte Finger genau entlang der Achsen des Koordinatensystems von OpenGL. Anders ausgedrückt: Man blickt in negative z-Richtung, wenn man den Monitor ansieht. Die x-Werte werden nach rechts und die y-Werte nach oben hin größer.

Durch Angabe von Koordinaten mit glVertex* ist es möglich, eine statische Szene zu beschreiben und das Rendering OpenGL zu überlassen. Sogar ein ‘Walk Through’ durch eine Szene lässt sich mit einigem Aufwand implementieren, wenn die Koordinaten für jeden Punkt jedes Objekts der Szene Bild für Bild, abhängig vom Standort des Betrachters, neu berechnet werden.

Glücklicherweise verfügt OpenGL über elegante Mechanismen zum Transformieren der über glVertex* angegebenen Koordinaten. Das Beispielprogramm macht von diesen Transformationen für die Drehungen des Würfels Gebrauch.

Der Schlüssel zu unterschiedlichen Sichten auf eine Szene, wie sie zum Beispiel beim Durchwandern derselben auftreten, liegt in der sogenannten ModelView Transformation. Die Objekte der Szene werden nur einmal definiert; Änderungen der Ausrichtung, Position oder Größe übernimmt die Model Transformation. Eine Änderung der Sicht auf die Szene wird durch die View Transformation und die Art der Projektion beschrieben. Die View-Transformation legt Standort und Blickrichtung fest, die Projektion bestimmt gewissermaßen das Objektiv der Kamera, mit der die Szene aufgenommen wird. Die ModelView Transformation lässt zwei verschiedene Interpretationen zu: Möglichkeit Eins geht davon aus, dass die Befehle glRotate* und glTranslate* die Kamera in der Szene umherschwenken und positionieren. Die zweite Sichtweise nimmt an, die Kamera sei fix montiert und fotografiere die Szene immer entlang der negativen z-Achse. Die Objekte werden über die genannten Befehle in das von der Kamera eingefangene Bild gerückt.

Tatsächlich sind beide Sichtweisen korrekt und unterscheiden sich nur im Vorzeichen der jeweiligen Operation. OpenGL ist es gleichgültig, ob die Kamera nach links geschwenkt wird (View Transformation) oder die Szene sich unter der fest montierten Kamera nach rechts wegdreht (Model Transformation), da das entstehende Bild dasselbe ist. Beide Transformationen werden daher unter dem bereits gefallenen Begriff ModelView Transformation zusammengefasst.

Die wichtigsten räumlichen Transformationen Skalierung, Translation und Rotation lassen sich durch 4x4- Matrizen sowie Punkte in homogenen Koordinaten darstellen. Für jede neu über eine der Funktionen glScale*, glTranslate* oder glRotate* angegebene Transformation berechnet OpenGL eine passende Matrix und fasst sie mit den bereits gesammelten Matrizen zu einer neuen zusammen. Die resultierende Matrix wird für die Transformation von Punkten oder die Verrechnung mit weiteren Transformationen gespeichert (siehe Matrix-Mathematik (PDF) ).

In sample1.c veranschaulicht die Display-Funktion den Vorgang. Zunächst wird eine Verschiebung Tz-3 in die Transformationsschlange eingereiht. Danach erfolgt eine Rotation Ry um die y-Achse um rotY Grad gegen den Uhrzeigersinn. OpenGL merkt sich das Produkt der entsprechenden Matrizen in der ModelView-Matrix M1 = Tz-3 * Ry. Als Nächstes fordert der Code eine Rotation Rx um die x-Achse, die wiederum mit den bereits vorhandenen Transformationen verrechnet wird: M2 = Tz-3 * Ry * Rx. Schließlich folgt eine Translation in alle Richtungen um -0.5 Einheiten, T-0.5. Zusammenfassend ergibt sich die ModelView-Transformation alsM3 = Tz-3 * Ry * Rx * T-0.5.

Alle jetzt über glVertex*() angegebenen Koordinaten von Punkten v werden mit M transformiert: v -> M * v. Dabei ist die Reihenfolge der Befehle von besonderer Bedeutung. Der als Erstes im Quellcode ausgeführte Befehl ist der letzte, der auf die zu transformierenden Punkte wirkt. Es macht einen Unterschied, ob ein Objekt zunächst um eine Achse durch seinen Mittelpunkt gedreht und anschließend verschoben wird oder als Erstes die Verschiebung stattfindet und danach das verschobene Objekt um dieselbe (nun nicht durch seinen Mittelpunkt laufende) Achse gedreht wird - die endgültige Lage des Objekts wird im Regelfall unterschiedlich sein.

Wenn OpenGL die besprochenen Transformationen bei jedem Aufruf der Display()-Funktion erneut zur ModelView-Matrix hinzurechnet, wandert der Würfel des Beispielprogramms durch fortgesetzte Translationen und Rotationen von Bild zu Bild weiter in der virtuellen Szene umher, möglicherweise sogar aus dem sichtbaren Bereich heraus. Um das zu verhindern, muss die ModelView-Matrix für jedes neue Bild auf Null zurückgesetzt werden. Mathematisch geschieht dies durch Setzen der ModelView-Matrix auf die Einheitsmatrix, programmtechnisch übernimmt diese Aufgabe der Aufruf glLoadIdentity zu Beginn der Display-Funktion.

Der eingangs erwähnte ‘Walk through’ durch eine Szene lässt sich mit Hilfe von glTranslate* und glRotate* zumindest für Bewegungen in der Ebene relativ leicht implementieren. Die Kamera muss lediglich durch eine Drehung um die y-Achse in die richtige Richtung geschwenkt werden (glRotatef(Winkel,0.0,1.0,0.0)), bevor sie innerhalb der Szene positioniert wird (glTranslate3f (pos_x, pos_y, pos_z)). Drehwinkel und Position müssen mit umgekehrten Vorzeichen angeben werden (Sichtweise 1). Die Reihenfolge von glTranslate* und glRotate* im Code ist ebenfalls genau umgekehrt: Zuerst glTranslate* und dann glRotate*.

Christian Marten
arbeitet bei GE CompuNet in Hannover als Systemingenieur.

[1] James Foley, Andries van Dam, Steven Feiner, John Hughes, Richard L. Phillips; Grundlagen der Computergraphik; Einführung, Konzepte, Methoden; Addison-Wesley, Bonn 1994

[2] Renate Kempf, Chris Frazier; OpenGL Reference Guide; Addison-Wesley, Reading 1997

[3] Mason Woo, Jackie Neider, Tom Davis; OpenGL Programming Guide; Addison-Wesley, Reading 1997

Mehr Infos

iX-TRACT

  • Die Grafikbibliothek OpenGL erlaubt die Entwicklung von 3D-Anwendungen unabhängig vom Betriebssystem.
  • Mit Mesa 3D steht eine freie, OpenGL-ähnliche Implementierung auf einer Vielzahl von Systemen zur Verfügung.
  • Auf dem OpenGL-Utility-Toolkit GLUT lassen sich Anwendungen vom einfachen drehbaren Farbwürfel bis hin zu komplexen 3D-Echtzeitspielen aufbauen.

(ka)