Visual Studio Projekt herunterladen
In unserem ersten grafischen Projekt gehen wir einen kleinen Schritt zurück und arbeiten vorerst mit Funktionen statt mit Klassen. In der Datei main.cpp gibt es fünf Funktionen:
renderSquare
renderCircle
renderStar
display
main
Funktionen müssen wie Variablen erst deklariert werden, bevor sie verwendet werden können. In der Beschreibung der einzelnen Funktionen möchte ich allerdings anders herum vorgehen.
Die main-Funktion
{
glutInit(&argc, argv);
Die Funktion
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
Nach der Initialisierung von GLUT setzen wir unseren Darstellungsmodus auf RGB-Farben mit Hintergrundpuffer (Doublebuffering). Doublebuffering ermöglicht uns, in einen unsichtbaren Hintergrundspeicher zu zeichnen und diesen Speicherbereich erst nach dem Zeichnen darzustellen, womit unser Bild auf einen Schlag angezeigt wird.
Wir besitzen also zwei Puffer, einen zum Zeichnen und einen, der gerade angezeigt wird. Würden wir direkt in den gerade angezeigten Speicherbereich schreiben, könnte der Benutzer zusehen, wie das Bild gezeichnet wird.
glutCreateWindow(
Nachdem wir den Darstellungsmodus gesetzt haben, können wir ein Fenster, hier mit dem Titel "Formen" erzeugen.
glutDisplayFunc(display);
Jedes Mal, wenn das Fenster neu gezeichnet werden soll,
z.B. wenn es erzeugt wird oder sich seine
Größe ändert, soll GLUT unsere eigene
Funktion
glutMainLoop();
}
Anschließend rufen wir die Hauptschleife des
Programms auf. In unserem Fall läuft das Programm solange, bis
unser von GLUT verwaltetes Fenster wieder geschlossen wird. Dummerweise
springt GLUT danach nicht zurück in unsere
Die display-Funktion
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
Die ersten beiden Befehle löschen den Hintergrund des Anzeigefensters mit der Farbe Schwarz.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.5, 1.5,
-1.5, 1.5,
-1.0, 1.0);
OpenGL arbeitet mit verschiedenen Matrizen, um geometrische Transformationen durchzuführen. Wir werden noch mehrere dieser Matrizen kennenlernen. In unserem Beispiel möchten wir eine orthogonale (nicht perspektivische) Projektion wählen.
Dazu schalten wir mit
Mit dem Befehl
glColor3f(0.2f, 0.2f, 0.2f);
renderSquare();
glColor3f(0.8f, 0.8f, 0.8f);
renderCircle(50);
glColor3f(0.5f, 0.5f, 0.5f);
renderStar(5);
Nachdem das Ausgabefenster mit einer Farbe gelöscht wurde und unsere Achsen vorbereitet sind, setzen wir nacheinander verschiedene Farben und rufen wir unsere eigenen Zeichenroutinen auf.
glutSwapBuffers();
}
Gezeichnet wird alles, wie gesagt, in einen
Hintergrundpuffer. Durch den Aufruf von
Unsere display-Funktion besitzt keinen
renderCircle etc.
Stellvertretend für die Zeichenroutinen sei hier nur renderCircle erläutert.
{
OpenGL liefert selbst keine Routinen zum Zeichnen von
Kurven. Wir müssen das schon selbst in die Hand nehmen
und einen Kreis durch viele Dreiecke annähern. Die Anzahl der
Dreiecke übergeben wir der Funktion durch den
glBegin(GL_TRIANGLE_FAN);
glVertex2f(0.0f, 0.0f);
Wir möchten einen Dreiecksfächer mit dem Ursprung (0, 0) als Zentrum zeichnen. Den Ursprung setzen wir zuerst, danach fehlen uns noch die umlaufenden Punkte des Kreises, die in einer for-Schleife berechnet werden.
{
glVertex2f(x, y);
}
Trigonometrische Funtkionen wie Sinus und Cosinus werden in C++ nicht in Grad sondern in Radian angegeben, also in Werten zwischen 0 und zwei PI. OpenGL arbeitet größtenteils in Grad.
Um begrenzt viele Winkel zwischen 0 und zwei PI zu
druchlaufen, teilen wir zuerst
Wichtig ist, dass wir die ganzzahligen Werte
glEnd();
}
Wir verwenden hier durchgehend die Funtkion glVertex2f und nicht glVertex3f. Als Regel gilt: So wenige Daten wie möglich sollten an OpenGL weitergegeben werden, da jede weitere Koordinate verarbeitet werden muss und Zeit kosten würde.
Selbständige Programmierung
- Viel Spaß bei eigenen Formen...