In diesem Kapitel richten wir die notwendige Software ein, um unser Projekt mit C++ und OpenGL umzusetzen. Das Ziel ist es, eine plattformübergreifende Software zu entwickeln, die sowohl auf Windows, Mac als auch Linux lauffähig ist. Damit können Sie mit Teammitgliedern zusammenarbeiten, die möglicherweise unterschiedliche Betriebssysteme verwenden. Das nachfolgend beschriebene Setup ist unabhängig von vorhandenen IDEs oder Compilern und kann bei Bedarf am Ende des Kurses restlos entfernt werden.
Organisatorischer Hinweis: Dieses Kapitel bearbeiten wir gemeinsam zu unserem ersten Termin. Sie müssen daher nichts im Vorfeld vorbereiten.
Schritt 1: Projektordner einrichten
Die nachfolgende .zip-Datei enthält den Projektordner mit Ordnerstruktur und Konfigurationsdateien.
Laden Sie sich den für Sie passenden Ordner herunter und entpacken Sie ihn an einen Ort Ihrer Wahl. Im Laufe des Semesters werden Sie nach und nach die einzelnen Kapitel in diesem Ordner implementieren.

Den Inhalt dieses Ordners werden wir in der ersten Veranstaltung im Detail besprechen.
Schritt 2: Compiler, Debugger und Entwicklungsbibliotheken installieren
Um C++ Code auszuführen muss dieser zuerst kompiliert werden. Wir nutzen im Rahmen der Computergrafik Veranstaltungen den Compiler CLANG.
CLANG ist ein moderner Compiler und stammt ursprünglich von Apple. Mittlerweile wirken auch Microsoft und Google an der Entwicklung mit. Da er auch aktuelle Plattformen wie Apple Silicon oder Windows on ARM unterstützt, ist er ideal für unseren Einsatz in der Lehre geeignet. Gleiches gilt natürlich auch wenn Sie Ihr Spiel für Mac, PC und Konsole herausbringen möchten und dabei jeweils die letzten 10% Performance heraus kitzeln wollen.
Als Debugger nutzen wir LLDB. Dieser stammt vom gleichen Entwicklerteam und harmoniert daher sehr gut mit CLANG. Außerdem verwenden wir clangd als Sprachserver der uns später Syntax-Highlighting in der IDE liefert. Zusätzlich nuten wir noch Make zur Automatisierung unseres Build-Prozesses. Make ist ebenfalls nützlich, um Aufgaben wie das Verpacken von 3D-Modellen, das Komprimieren von Texturen und das Kopieren von Sounds zu automatisieren, ohne von einem bestimmten Betriebssystem oder einer IDE abhängig zu sein.
Um OpenGL nutzen zu können sind je nach Betriebssystem einige zusätzliche Besonderheiten zu beachten. Wir nutzen daher die Bibliothek GLFW die uns die Fensterverwaltung abnimmt und eine einheitliche Schnittstelle zur OpenGL API bereitstellt.
Wir schauen uns nun an wie wir diese Software auf der jeweiligen Platform installieren:
Linux
Unter Linux werden die benötigten Pakete über den jeweiligen Paktmanager installiert. Unter Ubuntu 24.04 LTS funktioniert das wie folgt:
$ sudo apt install clang clangd lldb make libglfw3 libglfw3-dev
Bestätigen Sie eventuelle Rückfragen mit Enter. Sobald die Installation abgeschlossen ist, ist Ihr System startklar.
Falls Sie eine andere Distribution verwenden, kann es sein, dass die Pakete bei Ihnen anders heißen.
macOS
Unter macOS sind alle nötigen Tools in einem praktische Bundle namens Command Line Developer Tools zusammengefasst. Sie müssen dazu nicht das komplette XCode installieren.
Unabhängig davon ob Sie XCode nutzen oder nicht, öffnen Sie ein Terminal und führen folgenden Befehl aus um die Command Line Developer Tools zu installieren.
$ sudo xcode-select --install
Entweder Sie erhalten eine Mitteilung, dass die Tools bereits installiert sind oder es öffnet sich ein Dialog um sie zu installieren oder zu aktualisieren. In jedem Fall ist Ihr System im Anschluss an diesen Befehl startklar. Nach jedem Update auf eine neue macOS Version kann es notwendig werden, diesen Befehl erneut auszuführen.
Führen Sie anschließend folgenden Befehl aus und notieren Sie sich die Ausgabe.
$ xcrun -f lldb-dap
Dieser zweite Befehl sucht auf Ihrem System nach der Datei lldb-dap, einer Komponente des Debuggers. Notieren Sie sich den Pfad der im Terminal ausgegeben wird. Sie werden ihn später beim Einrichten des Debugging benötigen. Auf meinem Rechner lautet dieser Pfad: "/Applications/Xcode.app/Contents/Developer/usr/bin/lldb-dap"
Windows 10 / 11
Unter Windows benötigen wir MSYS2. Dabei handelt es sich um eine Sammlung von Linux-Tools die für die Windows Plattform kompiliert wurden. Damit haben wir auf der normalen Windows Kommandozeile Zugriff auf den Compiler und die üblichen Kommandozeilenwerkzeuge wie ls, rm, make und so weiter. Das funktioniert sowohl auf den bekannten x86-64 Prozessoren als auch auf den neuen ARM Prozessoren.
Besuchen Sie die MSYS2 Website und laden Sie sich die aktuellste Version herunter und installieren Sie die MSYS2.
ACHTUNG: Der Installationsordner darf keine Leerzeichen oder Sonderzeichen enthalten.
Im Folgenden gehe ich davon aus, dass Sie den Standard Installationsort C:\msys64 beibehalten. Falls Sie davon abweichen, achten Sie darauf, auch in den folgenden Anweisungen entsprechende Anpassungen vorzunehmen.
Wenn die Installation fertig ist, lassen Sie das Häkchen Run MSYS2 now aktiviert. Sie landen dann direkt im MSYS2 Terminal. In diesem Terminal geben Sie folgende Befehle ein. Bestätigen Sie eventuelle Rückfragen mit der Enter Taste.
Windows x86_64:
$ pacman -S make mingw-w64-clang-x86_64-clang-tools-extra mingw-w64-clang-x86_64-lldb mingw-w64-clang-x86_64-glfw
- oder alternativ -
Windows on ARM:
$ pacman -S make mingw-w64-clang-aarch64-clang-tools-extra mingw-w64-clang-aarch64-lldb mingw-w64-clang-aarch64-glfw
Die installierten Pakete landen in dem Ordner den Sie weiter oben als Installationsordner für MSYS2 ausgewählt haben. Damit andere Programme darauf Zugriff haben, müssen wir die entsprechenden Pfade dem Betriebssystem bekannt geben.
Suchen Sie im Startmenü nach Umgebungsvariablen bzw. Environment variables und öffnen Sie die passende Seite der Systemsteuerung. Im oberen Teil des Fensters unter "Benutzervariablen für …" wählen Sie den Eintrag "Path" aus und klicken auf Bearbeiten. Hier fügen Sie die folgenden Einträge hinzu:
Windows x86_64:
C:\msys64\clang64\bin
C:\msys64\clang64\lib
C:\msys64\clang64\include
C:\msys64\usr\bin
- oder alternativ -
Windows on ARM:
C:\msys64\clangarm64\bin
C:\msys64\clangarm64\lib
C:\msys64\clangarm64\include
C:\msys64\usr\bin
Hinweis: Die Reihenfolge der Einträge ist wichtig!
Das wars. Nun ist ihr System startklar.
Schritt 3: Testen ob alles funktioniert
Öffnen Sie unter Linux oder macOS ein neues Terminal Fenster oder unter Windows ein neues Power Shell Fenster. Tippen Sie dann nacheinander die folgenden Befehle ein und prüfen Sie das jeder Befehl ihnen eine Versionsnummer anzeigt (bedeutet ihr Computer hat das Programm gefunden) und keine Fehlermeldung.
$ clang++ -v
Ubuntu clang version 18.1.3
$ lldb -v
lldb version 18.1.3
$ make -v
GNU Make 4.3
Falls eine Fehlermeldung wie "command not found" erscheint, prüfen Sie noch einmal gewissenhaft alle vorherigen Schritte. Wir werden auch in Zukunft immer mal wieder das Terminal oder die Power Shell benötigen und es ist daher wichtig, dass dies problemlos klappt.
Schritt 4: Visual Studio Code installieren
Wir verwenden in dieser Veranstaltung Visual Studio Code als IDE. VSCode wird von Microsoft als Open-Source-Projekt entwickelt und ist sowohl für Windows, macOS als auch Linux verfügbar. Falls Sie bereits andere Visual Studio-Editionen installiert haben, ist das kein Problem. Sie können VSCode problemlos zusätzlich installieren. Besuchen Sie die Visual Studio Code Download Seite und laden Sie die passende Installationsdatei für Ihr Betriebssystem herunter. Es gibt unterschiedliche Versionen für Windows x86_64 und Windows on ARM sowie für Intel Macs und Apple Silicon. Wählen Sie die passende Version.
Interessante Randnotiz: Der Chefentwickler von Visual Studio Code ist Erich Gamma. Er ist Mitglied der "Gang of Four" und Mitautor des Buchs "Design Patterns - Elements of Reusable Object-Oriented Software", einem Standardwerk über Entwurfsmuster, das Ihnen in Ihrem Studium möglicherweise bereits begegnet ist.
Erweiterungen für VSCode
VSCode ist modular aufgebaut. Standardmäßig hat es die Funktionen eines besseren Texteditors. Mit Hilfe von Erweiterungen lässt sich der Support für diverse Programmiersprachen, Debugger und mehr nachinstallieren. Öffnen Sie VSCode, gehen Sie in das Erweiterungen Menü und installieren Sie die folgenden Erweiterungen:
- clangd: C/C++ completion, navigation and insights (Herausgeber: LLVM)
- LLDB DAP: LLDB debugging from VSCode (Herausgeber: LLVM)
- Shader languages support for VS Code: Syntax highlighter for shader language (hlsl, glsl, cg) (Herausgeber: slevesque)
- Wavefront: Grammars for Wavefront .obj and .mtl files. (Herausgeber: Damien Seguin)
- Compare Folders: Compare folders by contents, present the files that have differences and display the diffs side by side (Herausgeber: MoshFeu)
Debugger Pfad einstellen
Wenn Sie die LLDB DAP Erweiterung installiert haben und versuchen zu debuggen werden Sie eine Fehlermeldung erhalten. Das ist normal. Klicken sie einfach den Button "Open Settings" und tragen Sie dann den Pfad zur Datei lldb-dap bzw. lldb-dap.exe ein.
Linux: Unter Linux lautet der Pfad auf meinem System /usr/lib/llvm-18/bin/lldb-dap
macOS: Falls Sie einen Mac nutzen, haben Sie diesen Pfad bereits oben unter Schritt 2 ermittelt.
Windows: Unter Windows haben wir diese Datei mit MSYS2 installiert. Der Pfad hängt also ab von Ihrer Plattform. Auf meinem System unter Windows x86_64 lauter der Pfad C:\msys64\clang64\bin\lldb-dap.exe und auf Windows on ARM lautet er C:\msys64\clangarm64\bin\lldb-dap.exe
Falls der Pfad bei Ihnen abweicht und die Fehlermeldung weiterhin erscheint, nutzen Sie die Suchfunktion Ihres Rechners um nach der Datei zu suchen.
Schritt 5: Projektordner öffnen
Starten Sie Visual Studio Code und klicken Sie dort auf Ordner öffnen um den in Schritt 1 erstellen Projektordner zu öffnen. In diesem Ordner können Sie nun mit der Implementierung des ersten Kapitels beginnen.
Hello World in C++
Die Erfinder der Programmiersprache C sind auch die Urväter der Hello-World-Programme. Was liegt also näher, als dass wir unseren ersten Einstieg in die C/C++ Programmierung ebenfalls mit einem Hello World! beginnen.
// Hello World in C-Style C++
#include <cstdio>
int main()
{
printf("Hello World!\n");
return 0;
}
Speichern Sie die Datei und kompilieren sie das Programm indem Sie in der Kommandozeile folgendes eingeben:
$ make cgm_01
Wenn kein Fehler erscheint können Sie das Programm anschließend mit folgendem Befehl starten:
$ bin/cgm_01
Hier eine Erklärung der einzelnen Zeilen:
// Hello World in C-Style C++ In C und C++ ist jede Zeile die mit // beginnt ein Kommentar. Kommentare erlauben es dem Entwickler, Notizen zu machen. So kann er selber, aber auch andere den Code besser verstehen. Der Compiler ignoriert diese Zeile komplett.
#include <cstdio> Mit Hilfe von #include Statements werden Funktionen aus anderen Bibliotheken oder Dateien in unser Programm hinzugeladen. Hier laden wir die Bibliothek stdio (kurz für Standard-Input-Output). Dies ist nötig damit wir später die Funktion printf nutzen können um Text im Terminal auszugeben. Das Präfix "c" im Namen der Bibliothek deutet daraufhin, dass wir hier auf Funktionen der Programmiersprache C zurückgreifen. int main() Hier definieren wir die Funktion main. Ein C-Programm kann aus vielen Funktionen bestehen, benötigt aber mindestens eine Funktion mit dem Namen main. Dies ist der Einstiegspunkt unseres Programms und wird immer aufgerufen, wenn unser Programm startet. Der Parameter int vor dem Funktionsnamen gibt an, dass diese Funktion einen numerischen (int = Integer) Wert als Ergebnis zurück gibt.
printf(“Hello World!\n”); Hier wird die Funktion printf aufgerufen. Es wird ein String als Parameter übergeben. Hiermit wird ein Text auf der Konsole ausgegeben. Das abschließende \n ist ein Zeilenumbruch damit der Cursor in die neue Zeile springt.
return 0; Gibt 0 als Rückgabewert unserer main Funktion zurück. Hiermit teilen wir dem Betriebssystem mit, dass unser Programm keinen Fehler verursacht hat. Falls innerhalb unseres Programms ein Fehler auftritt, würden wir hier einen Wert ungleich 0 zurückgeben und Windows könnte dann zum Beispiel einen Fehlerbericht senden. Der Steam Launcher prüft ebenfalls diesen Wert um den Entwickler über Abstürze seines Spiels zu informieren.
Warum C-style C++?
Wie Sie vielleicht bereits festgestellt haben, ist der Quellcode nahezu identisch mit dem eines Hello-World-Programms in C. Der Grund dafür ist, dass wir in diesem Beispiel die C-Standardbibliothek verwenden und somit die Syntax von C nutzen. Dies ist in der Spieleentwicklung nicht ungewöhnlich. Wenn die Performance eines Programms von höchster Priorität ist, bietet C oft einen Vorteil. Dazu zählt auch unsere Grafikbibliothek GLFW, die bewusst auf Objektorientierung verzichtet und in C entwickelt wurde, um maximale Leistung zu gewährleisten.
Es gibt zahlreiche Bereiche, in denen C nach wie vor C++ vorgezogen wird. Gleichzeitig ermöglicht der Einsatz von C-Syntax in Verbindung mit einem C++-Compiler die Verwendung von sowohl C- als auch C++-Bibliotheken, während man die volle Kontrolle über die Software behält. Diese Herangehensweise vereint die Vorzüge beider Sprachen und maximiert Effizienz und Flexibilität.
Wir nutzen in diesem Modul C++
Bei der Arbeit an komplexeren Projekten kann C schnell unübersichtlich werden. C++ bietet mit Klassen und Objekten Werkzeuge, die es Entwicklern erleichtern, komplexe und abstrakte Konzepte zu verstehen und umzusetzen. Das new-Schlüsselwort vereinfacht zudem die Verwaltung von Speicher auf dem Heap.
In unserem Projekt übernimmt GLFW viele hardware-nahe Aufgaben. Daher können wir getrost C++ für die Entwicklung des restlichen Softwareteils nutzen, um von den Vorteilen der Sprache zu profitieren.
So sieht ein einfaches "Hello World"-Programm in einer modernen C++-Variante aus:
// Hello World in C++
#include <iostream>
int main()
{
std::cout << "Hello World!" << std::endl;
}
Dieses Beispiel verwendet Streams um mit der Textausgabe zu kommunizieren. Wir werden diese später noch für andere Aufgaben nutzen.
Ihnen fällt vielleicht auf, dass ich das return 0; Statement weggelassen habe und sich die Software trotzdem ohne Warnungen kompilieren lässt. Dies ist eine Besonderheit der main(). Es hat sich etabliert diese Zeile wegzulassen und stattdessen lediglich im Fehlerfall ein return zu verwenden. Der Compiler akzeptiert diese Schreibweise als vollkommen okay, also einfach nicht wundern.
Build Prozess verstehen
Wir haben weiter oben den Befehl make genutzt um unser Programm zu kompilieren. Make prüft zuerst ob sich eine Datei geändert hat und kompiliert diese nur falls das Änderungsdatum neuer ist. Hinter den Kulissen ruft make den Compiler im Terminal auf. Das können wir auch selber.
Die Befehle die Make ausführt lauten wie folgt:
$ mkdir -p obj
$ clang++ -c cgm_01/main.cpp -g -o obj/cgm_01/main.o
$ mkdir -p bin
$ clang++ obj/cgm_01/main.o -g -o bin/cgm_01
Führen Sie die Befehle manuell nacheinander aus und beobachten sie welche Dateien in Ihrem Projektordner durch diese Befehle erzeugt oder verändert werden. Versuchen Sie Zeile für Zeile nachzuvollziehen was die einzelnen Befehle machen.
Können Sie selber herausfinden was der Befehl make clean macht? Schauen Sie dazu ins Makefile und versuchen Sie die passende Stelle zu finden.
Hausaufgabe
Bearbeiten Sie eigenständig bis zur nächsten Veranstaltung Kapitel 2 vor. Das heißt:
- Folgen Sie dem Tutorial auf meiner Website und implementieren Sie den Inhalt des Kapitels im passenden Unterordner. Für Kapitel 2 ist dies der Ordner cgm_02.
- Alle Kapitel bauen aufeinander auf. Es empfiehlt sich daher den Inhalt des aktuellen Kapitel in den Ordner des nächsten Kapitels zu kopieren bevor Sie beginnen.
- Heben Sie die Inhalte der vorherigen Kapitel auf, so dass Sie diese auch in Zukunft noch starten können. Wir benötigen diese später noch.
- Zu Beginn der nächsten Veranstaltung sollte sich Ihr Code kompilieren und starten lassen. Außerdem sollten Sie verstehen was dort passiert.
- Lesen Sie weitere Quellen zum Thema. Sie finden weiterführende Links im jeweiligen Kapitel.
Bereiten Sie 3 Fragen zum nächsten Kapitel (Kapitel 2) vor, mit denen wir uns im nächsten Plenum ausgiebig auseinandersetzen.
- Die 3 Fragen müssen Sie zu Beginn der nächsten Veranstaltung abgeben.
- Ihre Fragen müssen sich auf das jeweilige Kapitel beziehen.
- Es können einfache Verständnisfragen sein oder auch Diskussionsfragen um das Thema aus einem anderen Blickwinkel zu betrachten.