ComputerBase

Bericht: „Quake Wars“ mit Raytracing

von Daniel Pohl

Vorbemerkung

Mit „Quake Wars mit Raytracing“ geht unsere Gastautoren-Artikelserie in eine neue Runde. Nachdem Daniel Pohl, damals noch als frisch gebackener Uniabsolvent, Anfang 2007 mit „Raytracing in Spielen [1]“ den ersten Artikel über seine Forschungsarbeiten auf dem Gebiet Raytracing auf ComputerBase veröffentlichte, mit „Raytracing in Spielen 2.0 [2]“ Anfang 2008, mittlerweile als Angestellter beim Chip-Hersteller Intel, die Fortsetzung nach schob und sich Nvidia im August 2008 dazu eingeladen fühlte, mit „Die Zukunft der 3D-Grafik [3]“ die eigene Sicht der Dinge darzulegen, ist nun wieder Daniel Pohl an der Reihe.

Wir weisen darauf hin, dass der nachfolgende Artikel ohne Mitarbeit der ComputerBase-Redaktion entstanden ist und allein die Meinung des Autors bzw. seines Arbeitgebers widerspiegelt. Dennoch freuen wir uns, unseren Lesern erneut die letzten Entwicklungen auf dem Sektor „Raytracing in Spielen“ sowie einen weiteren Beitrag im Rahmen der im Jahr 2007 gestarteten, öffentlichen Diskussion „Raytracing vs. Rasterisierung“ näher bringen zu können – weitere Beiträge und Meinung jederzeit willkommen!

Zeitreise ins Jahr 2004...

Eine Szene aus dem großen Computerlabor der Universität des Saarlandes: Zwanzig über ein Netzwerk miteinander verbundene PCs, ausgestattet mit jeweils zwei Prozessoren, laufen heiß und haben nur eines im Kopf: Die verteilte Berechnung einer „geraytracten“ Version von Quake 3 [4]. Obwohl die Auflösung von 512x512 bei einer Framerate von 20 Bilder pro Sekunde nicht an die Standards aktueller Spiele anknüpft, ist das Erstaunen der Zuschauer, die das erste Mal einen 3D-Shooter komplett mit Raytracing berechnet sehen, dennoch recht groß. Es werden Special-Effects gezeigt, die mit der herkömmlichen Rasterisierung so zuvor nicht in Spielen möglich waren – ach ja, das war übrigens schon im Jahre 2004, als es die meisten Leute noch nicht wagten, die Worte „Raytracing“ und „Echtzeit“ in einem Satz zu benutzen.

... und zurück ins Jahr 2008

In einem neuen Forschungsprojekt des Intel-Raytracing-Teams wagt man sich dieses Mal an das Spiel „Enemy Territory: Quake Wars“ von id Software und Splash Damage als Vorlage zum Raytracen. Im weiteren Verlauf des Artikels schildert Intels Research Scientist Daniel Pohl den Entwicklungsprozess inklusive der Herausforderung, die es zu bewältigen gab, und den Vorteilen, die Intel erreichen konnte. All' dies half dem Forschungsteam, mehr Wissen über Echtzeit Raytracing im Zusammenhang mit Spielen zu erlangen.

Bekanntlich sagt ein Bild mehr als Tausend Worte. Und ein geraytractes Bild sagt noch viel mehr und daher haben wir eine Menge Screenshots zur Veranschaulichung mit in die folgenden Abschnitte gepackt. Doch bevor wir im Detail abtauchen, soll das folgende Videos, „Quake Wars“ mit Raytracing im Überblick zeigen.

Video abspielen

Erste Schritte

Am Anfang war das Licht

Für dieses Projekt starteten wir damit, den Renderer von Null auf komplett neu zu schreiben. Daher sahen die ersten Bilder, die wir bekamen, auch nicht nach der üblichen Raytracing Qualität aus, sondern zeigten nur die grundlegenden Teile der Geometrie ohne jegliche Shader oder Texturen.

Quake Wars: Raytraced ohne Texturen
Quake Wars: Raytraced ohne Texturen

Normalerweise laden Spiele ihre Geometrie aus einer Vielzahl von verschiedenen Modellformaten – entweder erzeugt über den Ingame-Editor, oder durch externe Modellierungswerkzeuge. Nachdem man verifiziert hat, dass keine Objekte vergessen wurden, kann man sich um das Laden der Texturen kümmern. Moderne Spiele haben oft ihre eigene Materialbeschreibungssprache, mit der Designer auf einfache Art und Weise Texturparameter modifizieren, oder Texturen übereinander blenden können. Dasselbe gilt für die Nutzung von Bumpmaps über Specularmaps bis hin zu kleinen programmierbaren Shaderprogrammen mit einer Auswertung von mathematischen Ausdrücken. Wertet man diese Informationen aus, so kann man das obige Bild nun mit den dazugehörigen diffusen Texturen rendern.

Quake Wars: Raytraced mit Texturen (ohne Beleuchtung)
Quake Wars: Raytraced mit Texturen (ohne Beleuchtung)

Alle aktuellen Spiele benutzen derzeit eine Renderingtechnologie namens „Rasterisierung“. Diese benötigt oft komplizierte Programmierarbeit, da zum Erzeugen von Special Effects (wie z.B. Schatten oder Spiegelungen) Annäherungen benötigt werden, die durch mehrere Rendering-Durchgänge erzeugt werden, deren Ergebnisse zudem oft in auflösungslimitierten Texturen zwischengespeichert werden. In manchen Fällen können diese Approximationen deshalb deutlich sichtbar fehlschlagen.

Lasst uns einen genaueren Blick auf Schatten werfen. Mit Raytracing muss man lediglich den Pfad vom Licht zur Oberfläche verfolgen und feststellen, ob das Licht auf dem Weg geblockt wird, oder aber ans Ziel gelangt. Dies kann sehr einfach anhand eines Strahls (dem so genannten „Schattenstrahl“) erreicht werden. Wenn der Strahl von der Lichtquelle die betrachtete Oberfläche erreicht, dann ist dieser Punkt der Oberfläche beleuchtet. Falls nicht, so liegt er im Schatten. Das Spiel Quake Wars findet hauptsächlich in großen Außenarealen statt, wodurch die wichtigste Lichtquelle die Sonne darstellt. Diese Beleuchtungsquelle konnten wir sehr einfach hinzufügen und erhielten damit – wie erwartet – auch die entsprechenden Schatten.

Quake Wars: Raytraced mit Texturen (beleuchtet)
Quake Wars: Raytraced mit Texturen (beleuchtet)

Transparenzen

Anstatt überall richtige 3D-Geometrie zu benutzen, findet man in Spielen häufig Annäherungen an reale Geometrie mittels 2D-Vierecken (bzw. zwei Dreiecken), auf die eine Textur mit Transparenzwerten angewendet wird. Bei deren Berechnung gibt es in beiden Renderingverfahren Vorteile, aber auch Herausforderungen.

Beispiel einer teilweise transparenten Textur eines Astes auf einer Oberfläche bestehend aus zwei Dreiecken
Beispiel einer teilweise transparenten Textur eines Astes auf einer Oberfläche bestehend aus zwei Dreiecken

Es ist nicht gerade einfach, die korrekten Schatten von teilweise transparenten Dreiecken in einem Rasterisierer zu erzeugen. Das hierfür am häufigsten benutzte Verfahren in der Rasterisierung names „Shadow Mapping [5]“ liefert keine zusätzliche Information, die beim Erzeugen von unterschiedlich intensiven Schatten aus Transparenzen helfen würde. Daher werden solche Schatten oft fest in die Textur hinein gebacken. Deswegen können sie sich auch nicht ändern, wenn man die Lichtposition verändert (wenn man die Beleuchtung einer Szene zum Beispiel von Sonnenaufgang auf Sonnenuntergang umstellt).

Mit Raytracing geht's jedoch einfach. Wenn der Schattenstrahl ein Objekt trifft, so liest man an dieser Stelle den Transparenzwert der Textur aus und verfolgt den Strahl weiter, falls das Textursample an der Stelle transparent war. Dies ermöglicht interessante Special-Effects, erzeugt aber auch neue Herausforderungen. Das folgende Bild zeigt beispielsweise einen animierten „Kraftfeld-Shader“, der verschieden intensive Schatten am Boden wirft – abhängig davon, wie transparent das Kraftfeld an der Stelle ist.

Verschiedene Schatten, abhängig von den Transparenzen des Kraftfelds (1)
Verschiedene Schatten, abhängig von den Transparenzen des Kraftfelds (1)
Verschiedene Schatten, abhängig von den Transparenzen des Kraftfelds (2)
Verschiedene Schatten, abhängig von den Transparenzen des Kraftfelds (2)

Ein weiterer Vorteil im Falle von teilweise transparenten Objekten in einem Raytracer ist, dass sie nicht wie bei einem Rasterisierer nach ihrer Tiefe sortiert werden müssen, bevor man sie rendern kann. Das macht es für den Entwickler einfacher, kommt im Gegenzug jedoch mit erhöhten Kosten beim Rendern daher.

Wenn ein Strahl solch' eine transparente Oberfläche trifft, dann muss ein weiter Strahl von diesem Auftreffpunkt weiter in dieselbe Richtung geschossen werden (der ursprüngliche Strahl wird fortgesetzt). Wenn dies einmal passiert, dann ist der Einfluss auf die rechnerische Komplexität der Szene vernachlässigbar. Aber was passiert, wenn man zehn oder noch mehr dieser Flächen hintereinander aufgereiht hat? Dies kann zum Beispiel bei einem Baum passieren, der in der Computerwelt oft aus einem Mix vieler teilweise transparenter Vierecke besteht.

Modell eines Baums bestehend aus vielen teilweise transparenten Vierecken. (Bild erzeugt in Right Hemisphere Deep Exploration)
Modell eines Baums bestehend aus vielen teilweise transparenten Vierecken. (Bild erzeugt in Right Hemisphere Deep Exploration)
Dasselbe Modell des Baums mit Texturen und den Transparenzwerten. (Bild erzeugt in Right Hemisphere Deep Exploration)
Dasselbe Modell des Baums mit Texturen und den Transparenzwerten. (Bild erzeugt in Right Hemisphere Deep Exploration)

Als wir eine Vielzahl dieser Bäume in der Außenwelt renderten, wurde dies schnell zu unserem größten Flaschenhals. Durch mehrere Optimierungszyklen kamen wir auf einige Verbesserungen. Folgende Maßnahmen waren dabei am wichtigsten für die Performance:

Trotz vieler Optimierungen und Tweaks ist das Rendern der Bäume immer noch aufwendig. Wir haben die Kosten, um einen einzelnen Pixel zu rendern, in einem Farbschema visualisiert. Ein blauer Pixel repräsentiert dabei einen schnell zu berechnenden Pixel, ein roter einen langsamen (d.h. mit viel Rechenaufwand). Ein intensives Rot ist bedeutet mehr Aufwand als ein leichtes Rot. Wie man in folgendem Bild sehen kann, ist das Rendern der Bäume immer noch teurer als zum Beispiel das Rendern der spiegelnden Wasseroberfläche oder anderer Teile der Szene. Es ist also klar notwendig, dass in diesem Bereich des Renderns mit Raytracing noch weitere Forschungsarbeit geleistet wird, um noch mehr Verbesserungen zu finden.

Performance kodiert in Farben. Blau benötigt weniger Zeit als Rot.
Performance kodiert in Farben. Blau benötigt weniger Zeit als Rot.

Mehr Special-Effects!

Als wir in unserer geraytracten Version schlussendlich die gleiche Qualität wie im original Spiel erreicht hatten, begannen wir damit, weitere Special-Effects zu implementieren.

Raytracing ist sehr gut bei Spiegelungen und Brechungen und diese beiden Eigenschaften findet man im Alltag am häufigsten in Glas und Wasser. Wir haben uns genau daran gemacht.

Glas

Im original Spiel gibt es einen großen, soliden Dom. Wir haben die Oberflächeneigenschaften des Doms abgeändert, damit er wie aus Glas gemacht aussieht. Dabei benutzten wir den Brechungsindex für Glas (den man aus seiner Lieblingsformelsammlung entnehmen kann) und schrieben einen Shader, der die Spiegelungen und Brechungen von Glas simuliert. Der Code dafür benötigt nur etwa 15 Zeilen in unserer eigens entwickelten, HLSL-ähnlichen „Raytracing Shading Language“ und erzeugt beeindruckende Ergebnisse.

Dom mit Glas-Shader.
Dom mit Glas-Shader.

Wasser

Das Rendern von Wasser kann auf viele verschiedene Arten realisiert werden. Wir haben zwei Ansätze verfolgt: Wasser auf einer 2D-Oberfläche und „echtes“ 3D-Wasser*. Für die 2D-Variante haben wir eine Bumpmap benutzt, um Wellenbewegung zu simulieren. Bei dem 3D-Wasser haben wir ein Netz aus etwa 100.000 Dreiecken, das in verschiedene Sub-Netze aufgeteilt ist, eingesetzt. Diese Sub-Netze werden, falls sie sichtbar sind und damit zur Szene beitragen, in jedem Frame aktualisiert. Der Test auf Sichtbarkeit wird wiederum auch über das Schießen von einzelnen Strahlen realisiert.

Wasser mit einer 2D-Oberfläche und einer Bumpmap
Wasser mit einer 2D-Oberfläche und einer Bumpmap
Wasser mit einer echten 3D-Oberfläche bei niedrigem Wellengang (einstellbar per Parameter)
Wasser mit einer echten 3D-Oberfläche bei niedrigem Wellengang (einstellbar per Parameter)

* Implementierung von Jacco Bikker.

Die Zukunft von Raytracing

Wie bereits erwähnt, ist das Erzeugen realistisch aussehender Schatten auch mit Raytracing kein Kinderspiel. Analysiert man den aktuellen Stand unserer Demo, so bemerkt man, dass derzeit nur harte Schatten erzeugt werden. Moderne Spiele gehen jedoch mittlerweile mehr in die Richtung von weichen Schatten, die in den meisten Fällen noch mehr Strahlen benötigen würden. Dieses wichtige Thema bedarf intensiver Forschungsarbeit.

Um möglichst qualitativ hochwertige Bilder zu erzeugen, benötigt man zudem Anti-Aliasing. Adaptives Super-Sampling ist ein cleverer Ansatz, mit dem man eine Szene genau dort verfeinern kann, wo sich der Aufwand auch lohnt. Es gibt bereits experimentelle Implementierungen dieser Technik in Raytracing, jedoch müssen sie noch mehr getestet und für die bestmöglichen Ergebnisse optimiert werden. Nachdem sich die Industrie von den Multi-Core-Architekturen zu den Many-Core Architekturen (>10 Kerne) bewegt, wird es auch hier interessant sein, die Algorithmen zu verbessern, um die neu gegebene Hardware optimal ausnutzen zu können.

Obwohl Intels anstehende Many-Core Architektur namens „Larrabee“ hauptsächlich als Rasterisierungskarte entwickelt wurde, so ist sie dennoch ebenfalls komplett frei programmierbar. Dies eröffnet einige sehr interessante Möglichkeiten, um Raytracing auf der Larrabee-Architektur auszuführen.

Mein Dank geht an dieser Stelle neben meinen Kollegen auch an das Team von Intels „Visual Adrenaline“-Magazin, in dem sich eine englischsprachige Version dieses Artikels befindet. Ebenso ein Dankeschön an ComputerBase für das Hosten dieses Artikels. Und vielen Dank allen Lesern für die Aufmerksamkeit!

Das Performance-Problem

Performance ist der Hauptgrund, warum Raytracing derzeit noch nicht in kommerziellen Spielen benutzt wird. Verglichen mit einer spezialisierten Rasterisierungshardware (beispielsweise aktuelle GPUs von ATi oder Nvidia) ist Raytracing relativ langsam. Die fehlenden Hardware-Textureinheiten in unserem CPU-basierten Ansatz bringt einen großen Performanceeinbruch beim trilinearen Filtern aller Textursamples. Mit dem neuesten Intel-Quad-Socket-System (ausgestattet mit einem 2.66-GHz-Dunnington-Prozessor (6 Kerne) in jedem Sockel; macht insgesamt 24 Kerne) erreichen wir im Spiel zwischen 20 und 35 Frames pro Sekunde bei einer Auflösung von 1280 x 720 Pixel.

Nichtsdestotrotz ist dies eine enorme Verbesserung gegenüber den Experimenten aus dem Jahre 2004, die 20 Maschinen benötigten, um ein einfacheres Spiel langsamer in geringerer Auflösung zu rendern. Die größten Performance-Verbesserungen kommen von der weltweit betriebenen Forschungsarbeit auf dem Gebiet Raytracing und den neuen Plattformen mit mehreren Kernen, die die Parallelität von Raytracing ausnutzen.

Über den Autor

Daniel Pohl - AutorDaniel Pohl begann das Erforschen von Echtzeit-Raytracing für Spiele während seines Informatikstudiums an der Universität Erlangen-Nürnberg im Jahr 2004. Im Rahmen seiner Diplomarbeit hat er eine Version von Quake 4, die Raytracing benutzt, geschrieben. Im Jahr 2007 trat er der Raytracing-Gruppe bei Intel bei. Im Jahr 2008 zog er von Deutschland ins sonnige Kalifornien, wo er die Arbeit an spiele-relevantem Raytracing bei Intel fortsetzt.

Weitere Informationen

URL-Liste:

  1. http://www.computerbase.de/artikel/software/2007/bericht_raytracing_spielen/
  2. http://www.computerbase.de/artikel/hardware/grafikkarten/2008/bericht_raytracing_spielen_20/
  3. http://www.computerbase.de/artikel/hardware/grafikkarten/2008/kolumne_die_zukunft_3d-grafik/
  4. http://www.q3rt.de
  5. http://de.wikipedia.org/wiki/Shadow_Mapping
  6. http://www.computerbase.de/artikel/software/2007/bericht_raytracing_spielen/
  7. http://www.q4rt.de
  8. http://www.qwrt.de
  9. http://software.intel.com/en-us/visual-computing
Copyright © 1999–2012 ComputerBase GmbH