OpenGL mit der SDL initialisieren - C++ OpenGL Tutorials

Inhaltsverzeichnis[Verbergen]

Mit diesem ersten Tutorial beginne ich eine Serie von Tutorials zur Entwicklung von Spielen mit OpenGL unter C++. Das Erstellen des dazu nötigen Fensters und das Behandeln der Benutzereingaben werden wir mit der SDL (Simple DirectMedia Layer) durchführen. Durch die Verwendung dieser zwei Bibliotheken, sollten die damit entwickelten Spiele auch weitgehend plattformunabhängig sein.

Um einen einfachen Einstieg zu ermöglichen werden wir bei diesem Tutorial noch auf Klassen und andere C++ Spezialitäten verzichten und erst am Ende eine Klasse verwenden, die uns das Initialisieren von OpenGL erleichtern wird. Diese Klasse kann dann als Grundlage für alle weiteren OpenGL Programme verwendet werden. Auch in den weiteren Tutorials werden wir diese Klasse zum Initialisieren der OpenGL Schnittstelle verwenden.

1. Einrichten der Bibliotheken

Um OpenGL und die SDL in unserem Programm verwenden zu können müssen wir zuerst einmal die Header und Bibliotheken auf unserem Computer installieren. Wir verwenden dafür sowohl unter Linux als auch unter Windows am Besten den gcc-Kompiler.

1.1. Linux

Zuerst brauchen wir einmal die SDL Entwicklungsdateien und die dazugehörigen Laufzeitbibliotheken. Wir können sie einfach mit apt-get direkt über die Konsole installieren.

sudo apt-get install libsdl1.2-dev

Alternativ können wir die benötigten Pakete auch über den Packetmanager installieren.
Jetzt brauchen wir noch die OpenGL Linux Implementation Mesa. Sollte sie noch nicht installiert sein können wir sie wieder über die Konsole installieren.

sudo apt-get install libgl1-mesa-dev

Auch hier gibt es als Alternative natürlich wieder den Weg über den Packetmanager.

1.2. Windows

Die zur Zeit aktuelle Version der SDL bekommen wir unter http://www.libsdl.org/download-1.2.php. Wir sollten uns zumindest die Development Libraries herunterladen und die enthalten Dateien in die jeweiligen Ordner der MinGW Installation entpacken. Wichtig sind dabei die Ordner "include" und "lib". Zusätzlich muss noch die "SDL.dll" aus dem Ordner "bin" entweder in das Verzeichnis in dem die .exe-Datei unseres Programmes erstellt wird, oder in das Verzeichnis "windows/system32" kopiert werden. Alle anderen Dateien können wir löschen, da sie nicht benötitgt werden.
Für andere Kompiler müssen wir die Dateien an einen beliebigen Ort entpacken und dann die Pfade zu den Verzeichnissen in der Entwicklungsumgebung einstellen. Als Alternative kann ich auch noch die auf Eclipse basierende Entwicklungsumgebung Wascana empfehlen, die den MinGW Kompiler und alle von uns benötigten Bilbliotheken gleich automatisch einrichtet.
Die OpenGL Header und Libraries sollten normalerweise schon vorhanden sein, und wir können deshalb gleich weiter machen.

2. Einbinden der Bibliotheken

Am Anfang unseres Programmes müssen wir die Headerdateien der SDL und von OpenGL einbinden, damit wir auch auf diese Bibliotheken zugreifen können.

#include "SDL.h"        // SDL-Header
#include "SDL_opengl.h" // Bindet plattformabhängig die richtigen Header ein

Wer bereits OpenGL Code oder andere Tutorials gelesen hat wird sich vielleicht wundern, warum wir keine Header wie "GL.h" einbinden. Das liegt daran, dass das die "SDL_opengl.h" für uns übernimmt und darauf achtet das auf jedem Betriebssystem die richtigen Header in der richtigen Reihenfolge eingebunden werden.
Als nächstes wagen wir uns einmal an einen ersten Code heran.

#include "SDL.h"        // SDL-Header
#include "SDL_opengl.h" // Bindet plattformabhängig die richtigen Header ein 

#include <iostream>     // für Konsolenausgaben

using std::cout;    // Wir verwenden std::cout und
using std::endl;    // std::endl für die Konsolenausgaben

// Die main Funktion muss unter Windows unbedingt
// diese Form haben, da es ansonsten zu einem
// Linkerfehler kommen würde.
int main(int argc, char **argv)
{
  if( SDL_Init( SDL_INIT_VIDEO ) != 0 ) // Initialisieren des SDL Video Subsystems
  {
    cout << "Die SDL konnte nicht initalisiert werden (" << SDL_GetError() << ")" << endl;
    return 1;
  }

  cout << "Willkommen zum SDL Testprogramm." << endl;


  SDL_Quit(); // Herunterfahren der SDL Bibliotheken
  return 0;
}

Mit dem Aufruf der Funktion SDL_Init bereiten wir die SDL-Bibliothek zur Verwendung vor. Mit dem Parameter können wir sagen welche Subsystem wir verwenden wollen. In unserem Fall benötigen wir nur das Video System, wodurch uns auch schon Eingaben durch Tastatur und Maus ermöglicht werden. Später werden wir dann auch noch das Joystick Subsystem verwenden, dass wir aber jetzt noch nicht brauchen. Hat das Initialisieren funktioniert gibt die Funktion 0 zurück bei einem Fehler -1. Einen Fehlerstring können wir mit der Funktion SDL_GetError bekommen.
Am Ende fahren wir alle Subsystem mit einem simplen Aufruf von SDL_Quit wieder herunter und können das Programm beenden.

2.1. Kompilieren

Jetzt ist es endlich soweit, wir werden jetzt unser erstes OpenGL Programm kompilieren.

2.1.1. Linux

Zum Kompilieren gehen wir einfach in die Konsole und tippen folgendes ein:

g++ tomprogs_opengl_tutorial_01.cpp -o Tutorial01 -Wall $(sdl-config --cflags --libs) $(pkg-config gl --libs)

Dabei müssen wir natürlich darauf achten, dass wir uns im richtigen Verzeichnis befinden, und dass unsere Quellcodedatei auch wirklich "tomprogs_opengl_tutorial_01.cpp" heißt. Die beiden Befehle 'sdl-config' und 'pkg-config' geben dabei automatisch je nach Installation die benötigten Compiler- und Linkeroptionen zurück.

2.1.2. Windows

Auch unter Windows öffnen wir die Konsole, wechseln in das richtige Verzeichnis und geben folgendes ein:

g++ tomprogs_opengl_tutorial_01.cpp -o Tutorial01.exe -Wall -lmingw32 -lSDLmain -lSDL -lopenGL32 -mwindows

Wenn unsere Quellcodedatei auch wirklich "tomprogs_opengl_tutorial_01.cpp" heißt, dann müssten wir damit ohne Probleme kompilieren können.

Wenn wir alles richtig gemacht haben und alles funktioniert, dann sollten wir wenn wir das Programm kompilieren und ausführen unsere Willkommensmeldung zu sehen bekommen. Unter Windows werden wir wahrscheinlich keine Ausgabe bekommen, dort wird die Ausgabe in die Datei "stdout.txt" umgeleitet. Wenn wir dort unsere Willkommensnachricht finden, dann hat auch alles Funktioniert und wir können gleich weitermachen.

3. Erstellen des OpenGL-Fensters

Als nächstes werden wir ein Fenster für OpenGL erstellen. Zuerst setzten wir den Fenstertitel und aktivieren Doublebuffering. Doublebuffering bewirkt, dass wir zwei Bildspeicher bekommen, wobei wir immer in einen hineinzeichnen werden, während der andere angezeigt wird. Dadurch wird ein flüssiges Bild ermöglicht.
Wir könnten noch einige andere Attribute setzten, dir wir zur Zeit jedoch noch nicht brauchen.

// Fenstertitel setzen:
// Der erste Text steht in der Titelleiste des Fensters und der zweite in der Taskleiste.
SDL_WM_SetCaption( "Tomprogs Game Tutorials - First Try", "Tomprogs - First Try" );

// Doublebuffering aktivieren
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

Im nächsten Schritt können wir jetzt auch schon das Fenster erzeugen. Es geht eigentlich ganz einfach, wir müssen nur die Funktion SDL_SetVideoMode aufrufen und schon bekommen wir ein nagelneues OpenGL Fenster das nur darauf wartet ein Spiel rendern zu dürfen.

// Ein OpenGL Fenster mit einer Auflösung von 800*600 Pixeln und
// einer Farbtiefe von 32 Pixeln erzeugen.
SDL_SetVideoMode( 800, 600, 32, SDL_OPENGL );

Mit den ersten beiden Parameter bestimmen wir eine Fenstergröße von 800*600 Pixeln und mit dem dritten eine Farbtiefe von 32 Bit. Durch den letzten Parameter schließlich sagen wir der SDL, dass wir eine OpenGL Schnittstelle haben wollen.
Wenn wir jetzt kompilieren und unser Programm ausführen sehen wir wahrscheinlich nur kurz unser gewünschtes Fenster, dass aber sofort wieder verschwindet.

4. Ein Endlosschleife muss her

Der Grund für das sofortige beenden des Programmes ist, dass wir ja gleich nach dem Erstellen des Fenster unser Programm wieder verlassen und dabei natürlich auch das Fenster zerstören. Um das zu verhindern bauen wir nach dem Erzeugen des Fensters eine Endlosschleife ein. Doch diese Schleife soll natürlich nicht die gesamte Prozessorzeit des Programmes verheizen sondern hat einige wichtige Aufgaben ohne die ein Spiel nicht funktionieren könnte.
Jedes Programm das außerhalb der Konsole läuft bekommt vom Betriebssystem Nachrichten zugeschickt. Diese sollten wir nun als erstes in unserer Endlosschleife behandeln. Die Nachrichten werden dabei so lange zwischengespeichert bis wir sie uns holen und verarbeiten. Wir können uns nun mit der Funktion SDL_PollEvent die erste Nachricht aus der Nachrichtenschlange holen. Sobald keine Nachrichten mehr vorhanden sind gibt diese Funktion null zurück, und wir können andere Dinge machen, ohne das wir wichtige Nachrichten versäumen würden.
Dadurch das immer als erstes in der Endlosschleife die Nachrichten behandelt werden wird diese oft auch Nachrichtenschleife oder auf Englisch "messageloop" genannt.

// Enlosschleife
while(true)
{
  SDL_Event event; // Hier wird immer die neue Nachricht gespeichert

  while( SDL_PollEvent(&event) ) // Holen der nächsten Nachricht
  {
    // Bestimmen des Nachrichtentyps
    switch(event.type)
    {
      // Bei einer SDL_QUIT Nachricht sollte das Programm beendet werden.
      // Sie wird zb. verschickt wenn man auf das X beim Programmfenster
      // klickt.
      case SDL_QUIT:
        SDL_Quit(); // Herunterfahren der SDL
        exit(0);
        break;
      default:
        break;
    }
  }

  // Hierher kommt dann alles was das Spiel am Laufen hält...

}

Wie wir sehen können sind bei der SDL alle Nachrichten vom Typ SDL_event. In dieser Struktur gibt es ein Element mit dem Namen Typ, an dem wir erkennen können um was für eine Nachricht es sich handlet. In dieser ersten Version behandeln wir nur Nachrichten vom Typ SDL_QUIT, wobei wir bei Erhalt einer solchen Nachricht unser Programm einfach beenden.
Wenn wir jetzt unser Programm wieder kompilieren und ausführen, dann bekommen wir unser gewünschtes Fenster und es bleibt sogar solange erhalten bis wir es mit einem Klick auf das X beenden.

5. Ausblick

Jetzt sind wir ja doch noch am Ende von diesem Tutorial angekommen und haben bereits eine OpenGL Schnittstelle mit der SDL initialisiert. Das da noch weit mehr möglich ist wird wohl jedem klar sein, doch für ein erstes Tutorial sollte das einmal reichen.
Bis jetzt war noch nicht unbedingt sehr viel zum Sehen, aber im nächsten Tutorial geht es gleich weiter und wir werden unser erstes Dreieck zeichnen. Damit wir uns dann mit dem Initialisieren einfacher tun habe ich den Großteil vom Code, wie versprochen in eine Klasse ausgelagert, die wir dann ab jetzt in allen Tutorials verwenden werden.

Nächstes Tutorial: C++ OpenGL Tutorials - Ein erstes Dreieck

6. Quellcode

Hier gibts noch den vollständigen Quellcode dieses Tutorials zum Downloaden.

icon Quellcode OpenGL Tutorial 01 (3.58 kB 2008-07-14 20:27:13)

Und hier ist noch der Quellcode der Klasse zum Erstellen eines OpenGL Fensters. Eine kurze Erklärung dazu gibt es im nächsten Tutorial.

icon Klasse zum Initialisieren von OpenGL (3.42 kB 2008-07-13 00:52:46)


Wünsche, Anregungen und Kritik bitte über das Kontaktformular oder direkt an Diese E-Mail-Adresse ist gegen Spambots geschützt! Sie müssen JavaScript aktivieren, damit Sie sie sehen können.

Aktualisiert ( Samstag, 22. Oktober 2011 um 16:01 Uhr )