TERRORISTICA
Known Bugs / Issues:
-
Die Load-/Save-Funktion hat es leider nicht mehr in dieses Release geschafft,
weil es immer noch Probleme beim Sharen der von OpenGL verwendeten Objekte gibt
bzw. die Spielstände noch nicht korrekt gespeichert werden. Im Moment werden
lediglich Dummy-Dateien geschrieben.
- Die Performance auf dem Übungsrechner ist miserabel. Läuft am Freitag
bei der Präsentation schneller, da ich meinen eigenen Rechner mitnehmen
werde. Vielleicht könnten wir nach der Pause oder überhaupt als letzte
Gruppe drankommen (zwecks Computer aufstellen, Umbau, etc.)
Besonderheiten:
-
Waffen: Es sind 8 Waffen implementiert: Eine Schlagwaffe (Brechstange), 3 Schusswaffen
(Shotgun, Maschinengewehr, Raketenwerfer) und 4 mathematische Waffen. Um mathematische
Waffen bedienen zu können, muss zuerst das entsprechende Mathematik-Buch
gefunden werden, welches in jedem Level auf jeden Fall vorhanden ist. Einzige
Ausnahme ist die stärkste Waffe (der Convolution Filter), für den
ALLE Bücher benötigt werden. Falls ein Buch für die ausgewählte
Waffe noch nicht gefunden wurde, wird dies rechts unten am Bildschirm (unter
dem Namen der Waffe) angezeigt.
Mathematische Waffen haben den Vorteil, dass sie keine Munition benötigen,
da sie vollständig auf geistigen Fähigkeiten beruhen. Terroristen
können mathematische Waffen nicht verwenden.
- Cheat-Mode: Mit F1 werden mögliche Optionen eingeblendet. So ist z.B.
auch ein GOD-Mode vorhanden, sowie eine Funktion, um alle Waffen und Gegenstände
zu bekommen. Durch Drücken von F12 werden alle Gegner im Level getötet,
sodass man bequem alle Levels / Levelsequenzen / Outro / Models / Freihaus-Geometrie
sehen kann.
- Prof. B.: Wird im 4. und letzten Level in einem Raum von Terroristen bewacht.
Mehr wird nicht verraten (vor allem nicht, wie das Spiel ausgeht!).
Kurzbeschreibung
der Implementierung:
Zur Darstellung der statischen Geometrie wird ein BSP-Baum verwendet. Dabei werden im wesentlichen Quake3-Maps verwendet, welche allerdings davor in unser Datenformat konvertiert werden müssen. Hierfür haben wir einen eigenen Konverter geschrieben, der sich auf ein paar Codezeilen beläuft. Im Grunde wird die Quake3-Map etwas abgespeckt, da wir nicht alle Informationen für unser Spiel benötigen.
Zur Darstellung der Models verwenden wir das .MD3-Format, welches es erlaubt, Unter- und Oberkörper sowie den Kopf getrennt voneinander zu animieren. Die Models selbst haben wir dabei aus dem Internet, wobei Prof. B. von uns ein eigenes Skin erhielt, um dem Original ähnlich zu schauen.
Bei
der Beleuchtung hat sich einiges geändert: Lightmaps werden zwar noch geladen,
aber nicht mehr dargestellt, da alle vorkommenden Lichtquellen
in unserem Spiel vollkommen dynamisch sind. Für das Konzept der Lightmaps
fällt uns vielleicht noch etwas ein, um sie mit den dynamischen Schatten
integrieren zu können, ansonsten werden wir wohl auf Lightmaps verzichten.
Die Models selbst werden in einem Vertex-Shader beleuchtet, welcher im Prinzip
die Standard-OpenGL-Beleuchtung nachahmt, den einzelnen Models jedoch auch Self-Shadows
verleiht, was ansonsten nicht möglich wäre.
Gekrümmte Oberflächen können in Terroristica durch sogenannte Bezier-Patches dargestellt werden, welche beim Laden des Levels mit einstellbarem Tesselierungsgrad in einzelne Dreiecke umgerechnet werden. In dieser Version kommen allerdings keine Bezier Patches zum Einsatz, da diese im Freihaus nicht auftreten.
Features:
Culling:
- BSP-Trees: Für das Culling der statischen Geometrie kommen BSP-Trees
zum Einsatz. Dabei wird für jedes Frame ein sogenannter Cluster bestimmt,
in dem sich die Kamera gerade befindet. Von diesem Node des BSP-Trees ausgehend
wird der Baum traversiert, um alle sichtbaren Flächen zu gewinnen.
- PVS (Potentially Visible Sets): Mit Hilfe von PVS wird für jedes Cluster bestimmt, welche anderen Cluster möglicherweise sichtbar sind. Einzelne Cluster werden dabei durch angrenzende Portale definiert. Zur Laufzeit kann mit Hilfe von Bittests bestimmt werden, welche Cluster auf keinen Fall von der aktuellen Kamera-Position aus sichtbar sind.
-
Frustum-Culling: Alle sichtbaren Dinge wie statische Geometrie, Models, Gegenstände,
Lichtquellen, etc. werden zusätzlich noch mit Frustum-Culling verworfen,
wenn sie sich nicht im aktuellen Kamera-Frustum befinden.
- Occlusion-Culling: Da der gesamte Level mit voll-dynamischen Lichtquellen
ausgeleuchtet wird, müssen auch Lichtquellen auf irgendeine Art und Weise
verworfen werden, da selbst die beste Grafikkarte ein Multipass-Rendering von
ca. 15 Passes für alle Lichtquellen nicht mit akzeptabler Geschwindigkeit
durchführen kann.
Aus diesem Grund kommt für Lichtquellen die neue Occlusion-Query-Extension
zum Einsatz: Für jede Lichtquelle wird ihre Bounding-Box, also der Bereich
in den sie Licht abstrahlt, ohne Z-Write und ohne Color-Write mit eingeschalteter
Occlusion-Query gerendert. Ist dabei mehr als ein Pixel sichtbar, wird die gesamte
Lichtquelle als sichtbar angenommen, sofern diese nicht schon zuvor mit Hilfe
einer anderen Culling-Methode verworfen wurde. Dadurch treten bei geschickter
Platzierung der Lichtquellen maximal 4 oder 5 gleichzeitig auf, sodass das Spiel
auch auf einer GeForce 4 noch spielbar ist.
Models:
- Keyframe-Animation: Die Models werden über sogenannte Keyframes animiert.
Dabei ist das Model in mehrere Animationsphasen eingeteilt (Schiessen, Gehen,
Springen, Laufen, Sterben, etc.), wobei für bestimmte Frames dieser Phasen
für die einzelnen Körperteile (Unterkörper, Oberkörper und
Kopf) die Transformationsmatrizen abgespeichert sind. Zur Laufzeit werden diese
Matrizen in Quaternions umgewandelt, mit SLERP (Spherical Linear Interpolation)
der Quaternions entsprechend transformiert und wieder in Matrizen zurückgewandelt,
welche dann an OpenGL für die jeweiligen Körperteile übergeben
werden können.
-
Physik: Wert haben wir auf ein etwas realistischeres Verhalten der Models gelegt.
Bei einer Bewegung z.B. ist leicht festzustellen, dass der Spieler einer geringen
Beschleunigung ausgesetzt ist, wodurch er bei schnellen Drehungen oder abruptem
Stoppen noch einen Teil der Geschwindigkeit behält. Durch Implementierung
von Gravitation ist es auch möglich, Sprünge bzw. das automatische
Auf- und Ablaufen von Stiegen zu realisieren.
Collision Detection / Collision Response:
- Models <-> Geometrie: Diese Art der Collision Detection wird mit Hilfe
von Bounding Boxes und dem BSP-Tree bewältigt. Dabei wird im Wesentlichen
die Bounding Box des zu testenden Models den BSP-Tree "hinuntergeschoben".
Für die Collision Response wird eine sogenannte "Sliding Plane"
ermittelt, die der Spieler bei einer Kollision entlanggeht, abhängig von
seiner Geschwindigkeit.
- Models <-> Models: Hier funktioniert die Collision Detection auf dem
Prinzip der Bounding Spheres, wobei der Spieler bei einer Kollision in die Richtung
des Normalvektors des Punktes bewegt wird, an dem er kollidiert ist.
- Models, Geometrie <-> Projektile: Hier wird ein Strahl durch den gesamten
BSP-Tree geschossen und ein exakter Schnittpunkt ermittelt, an dem das Projektil
auf der Wand auftrifft. Für Models wird der Schnittpunkt mit der Bounding
Sphere ermittelt.
Sound:
- Models, Waffen: Jedes im Spiel vorkommende Model hat eigene Sounds, welche
über FMOD abgespielt werden. Ebenso hat jede Waffe ihren völlig individuellen
Sound beim Abfeuern.
- Hintergrundmusik: Für jedes Level kann eine eigene Hintergrundmusik definiert
werden. Dazu muss lediglich ein File verändert werden.
Content:
- Freihaus: Wie man an den folgenden Screenshots erkennen kann, kommt unser
Freihaus dem Original sehr nahe. In mehr als 3-monatiger Arbeit wurde das Freihaus
vermessen und in einem Level-Editor nachgebildet. Alle Texturen wurden mit einer
Digitalkamera photographiert und anschließend nachbearbeitet. Im einem
weiteren Bearbeitungsschritt wurden Normal-Maps für die jeweiligen Texturen
erstellt, welche beim DOT3-BumpMapping zum Einsatz kommen (mehr dazu später).
Auch Kleinigkeiten (welche uns jedoch sehr wichtig waren), wie z.B. Schaukästen,
Stiegenhausschilder, Beschriftungen, etc. sind vorhanden. Dies ist auch sehr
gut auf dem zweiten Screenshot zu erkennen.
Bild 1 - Freihaus, 2. Stock, grüner Bereich - Stiegenhaus
Bild 2 - Freihaus, 3. Stock, gelber Bereich -
Schaukästen, Türschild, "Rauchen Verboten"-Schild, Beschriftungen,
etc.
Beleuchtung:
- Per-Pixel DOT3 Bump Mapping: Jede Textur in unserem Spiel besteht aus einer
sogenannten "Base-Texture" und einer "Normal-Map". Zur Laufzeit
wird mit Hilfe von Register-Combiners das Bump Mapping realisiert. Auf Bump
Mapping bei den Models haben wir verzichtet, da es sehr schwierig ist, Normal-Maps
händisch zu erstellen und uns High-Poly-Counterparts der Models nicht zur
Verfügung stehen. Auf folgendem Screenshot kommt das Bump Mapping besonders
gut zur Geltung:
Bild 3 - Bump Mapping auf gesamter Geometrie
- Per-Pixel Lighting: Alle Lichtquellen fungieren mit Per-Pixel Lighting, d.h.
mit Hilfe von geeigneten "Attenuation-Maps"; das sind im Wesentlichen
3D-Texturen mit vorberechnetem Lichtabfall in alle Richtungen.
- Dynamische erstellbare Lichtquellen: Durch Gewehrfeuer, Raketen, etc. können
dynamisch neue Lichtquellen eingebunden werden. Dabei ist es z.B. auch möglich,
Projektilen eine eigene Lichtquelle zuzuweisen, was vor allem bei den mächtigeren
Schusswaffen (z.B. Raketenwerfer) zum Einsatz kommt.
- Dynamisch konfigurierbare Lichtquellen: Lichtquellen bestehen im Prinzip aus
mehreren Komponenten: Einer Position, einer Farbe, einer zugehörigen Textur,
einem Typ und einer sogenannten Lighting-Function.
Der Typ gibt dabei an, ob die Lichtquelle statisch ist oder
z.B. an einem Kabel baumelt und schwingt. Die Lighting-Function
gibt an, ob die Lichtquelle kurz Aufblitzen soll, ob sie flackert, etc. Dabei
ist jede beliebige Kombination möglich - desweiteren können jederzeit
neue Lighting-Functions für völlig neue Lichtquellen implementiert
werden. Hierzu muss lediglich eine mathematische Funktion für das Verhalten
der Lichtquelle implementiert werden.
- Echtzeitschatten: Da alle Lichtquellen dynamisch sind, werden auch alle Schatten
sowohl für Geometrie als auch für Models in Echtzeit dargestellt.
Dabei kommt ein etwas abgeänderter Shadowmap-Approach zum Einsatz, welcher
auch für Pointlights funktioniert. Der Trick dabei ist, eine mit Distanz-Werten
vorberechnete 3D-Textur zu verwenden, welche mit aktiviertem Z-Test in ein Cube-Map
Render-Target gerendert wird. Diese Shadow-Map wird später beim Rendern
der Geometrie in einem Vertex-Shader passend transformiert, sodass alle Pixel,
welche von der Lichtquelle aus nicht sichtbar sind, schattiert werden.
Durch die Verwendung von Shadow-Maps hat man einige Vorteile gegenüber
dem von z.B. DOOM 3 verwendeten Stencil-Shadow-Algorithmus: Unser Approach funktioniert
auch für transparente Geometrie, was bei Stencil-Shadows einfach nicht
möglich ist - außer man modelliert alle transparenten Teile einzeln,
was jedoch zu einer ENORMEN Fillrate-Belastung der Grafikkarte führt und
deshalb noch nirgends zu sehen ist.
Weiters ist Self-Shadowing der einzelnen Objekte automatisch vorhanden, d.h.
der Schatten eines Models kann auch auf das Model selbst fallen.
Echtzeitschatten sieht man auf den folgenden Screenshots besonders gut:
Bild 4 - Echtzeitschatten für mehrere Lichtquellen
auf mehreren Models, Self-Shadowing
Bild 5 - Echtzeitschatten für die gesamte
Geometrie, Lichteinfall einer zweiten Lichtquelle
Bild 6 - Transparente Echtzeitschatten einer schwingenden
Lichtquelle - in dieser Form mit Stencil-Shadows definitiv nicht möglich
AI (Artificial Intelligence):
- Event-Driven Finite State Machine: Alle Actors, welche nicht vom Spieler gesteuert
werden, verfügen über eine eigene AI, welche im Prinzip über
einen endlichen Automaten konzipiert ist. Dabei kann sich jeder Actor in einem
bestimmten Zustand befinden (z.B. Gehen, Angreifen, Alarm, Bewachen, etc.) -
durch äußere Einflüsse werden diese Zustände verändert,
z.B. wenn ein Terrorist getroffen wird, wenn er den Spieler sehen kann, etc.
Für die Bewegung selbst sind 3 Sensoren zuständig, die von der Position
des Actors ausgehend die umliegende Geometrie abtasten und jeden Actor so durch
die Map navigieren.
Programmiertechnisches:
- Modulares Design: Das gesamte Spiel ist so konzipiert / programmiert, dass
im Prinzip jederzeit ein MOD erstellt werden könnte. Alle Texturen, Effekte,
Explosionen, Rauchspuren, Waffen, Models, Sounds, Intro, Levelsequences, Maps,
Levels, etc. können jederzeit durch anderen Content ersetzt werden. Auch
Lichtquellen, Actors, Gegenstände, etc. können durch einfaches Ändern
eines Textfiles völlig anders positioniert werden.
- Vertex Shaders: Alle Passes, die in unserem Spiel gerendert werden müssen,
werden von einem Vertex Shader durchgeführt.
- Register Combiners: Ebenso wie Vertex Shader werden alle Per-Pixel-Operationen
mit Hilfe von Register Combiners realisiert.
Sonstiges:
- Curved Surfaces / Bezier Patches: Wie bei der 2. Abgabe bereits sichtbar,
können mit Hilfe von Quadratic Bezier Patches gekrümmte Oberflächen
erstellt werden, welche erst beim Laden des Levels in Dreiecke tesseliert werden.
Da im Freihaus solche Oberflächen aber nicht vorkommen, sind diese in der
3. Abgabe auch nicht mehr zu sehen, da wir den Freihaus-Content so original
wie möglich gestalten wollten.
- Smoke Trails, Explosionen: Mit Hilfe von Billboards können für jede Waffe völlig eigene Smoke Trails, Projektile und Explosionen definiert werden. Größe, Animation, Geschwindigkeit, Aussehen, etc. sind dabei völlig variabel und können für jede Waffe individuell eingestellt werden. Um einer Waffe einer anderes Aussehen zu verpassen, müssen lediglich das Model / die Texturen verändert und ein paar Parameter getweakt werden.
-
Decals: Einschusslöcher können für jede Waffe eigens definiert
werden. Auch animierte Decals (Maschinengewehr) sind dabei möglich. Größe,
Aussehen, Animation, etc. sind dabei natürlich wieder völlig variabel
einstellbar. So hinterlässt jede Waffe z.B. völlig unterschiedliche
Einschusslöcher, wenn ein Projektil auf der Wand auftrifft. Auch Blut und
Blutspritzer sind dadurch reichlich vorhanden, wie man auf dem folgenden Screenshot
sehen kann:
Bild 7 - Decals: Einschusslöcher, Blut
- 2D Bump Mapping: Im Menü ist 2D Bump Mapping implementiert, welches früher
sehr häufig verwendet wurde und für 2D-Graphik recht schöne Ergebnisse
liefert. Die Idee dahinter ist die Gleiche wie bei Emboss Bump Mapping.
Dadurch bekommen die einzelnen Menüpunkte ein etwas plastischeres Aussehen
- es entsteht der Eindruck, als würden sie sich vom Hintergrund abheben:
Bild 8 - 2D Bump Mapping
Verwendete Libraries:
Sämtliche
Render-Algorithmen, AI, Collision Detection, etc. wurden von uns implementiert.
Lediglich der Sound wird über eine externe Library, nämlich FMOD,
realisiert.
Verwendete Tools:
Die gesamte Level-Geometrie wurde mit GtkRadiant, einem Editor
für Quake3-Maps, erstellt. Zum Kompilieren der Maps wurde der Q3Map2-Compiler
verwendet, welcher eine erweiterte und verbesserte Version des Original-Compilers
von id-Software darstellt.
Alle Texturen wurden mit Adobe Photoshop nachbearbeitet, und die Normal-Maps
mit NVidias Normal-Map-Filter (Photoshop-Plugin) erstellt.
Links / Referenzen:
Quake3-Maps, BSP-Trees, PVS, MD3-Models, Keyframe-Animation:
www.gametutorials.com
Per-Pixel Lighting, Per-Pixel DOT3 Bump Mapping, Shadow Mapping, Vertex Shaders,
Register Combiners: developer.nvidia.com
Quake3-Map-Editor, GtkRadiant: www.qeradiant.com
Quake3-Map-Compiler, Q3Map2: shaderlab.com/q3map2
Sound, FMOD-Library: www.fmod.org