Zum 3DCenter Forum
Inhalt




Der lange Weg zum HDR-Rendering

1. Januar 2006 / von aths / Seite 1 von 3


   Einleitung

3D-Grafik ist ein einziger Schwindel. Das beginnt schon beim Begriff selbst: Was wir landläufig 3D-Grafik nennen, ist 2D-Grafik – die Ausgabe auf dem Monitor ist flach. Der Framebuffer, der vom Display angezeigt wird, ist ein 2D-Array von Farben. Während der Berechnung finden immerhin auch 3D-Transformationen statt, dank perspektivischer Projektion (für die aus bestimmten Gründen tatsächlich sogar eine 4D-Transformationen genutzt wird) lässt sich ein recht gutes 2D-Abbild einer 3D-Szene erstellen.

Um die Dreidimensionalität glaubwürdig zu machen, sind neben der Perspektive weitere Dinge notwendig. Zum Beispiel, dass eine korrekte Überdeckungsberechnung stattfindet: Was in der 3D-Szene von Vordergrundobjekten verdeckt ist, darf auf dem 2D-Bildschirm nicht zu sehen sein. Das leuchtet sofort ein und ist daher kaum einer Erwähnung wert. Was jedoch gerne unterschätzt wird, ist die Wichtigkeit von Beleuchtung. Ohne Lichtberechnungen wirkt alles flach: Eine graue Kugel ließe sich ohne Beleuchtung nicht vom Kreis unterscheiden.

Eine 3D-Szene zu beleuchten, reicht natürlich nicht. Um Oberflächenmaterialien zu simulieren, verwendet man in der Regel Texturen – in diesem Kontext meinen wir damit vorgefertigtes Bildmaterial. Für das Resampling des Bildes auf die 3D-Oberfläche werden Texturfilter-Formeln genutzt, die im Vergleich zum mathematisch exakten Resampling nur eine grobe Näherung bieten. Dafür sind die heute implementierten Verfahren vergleichsweise günstig, was die Zahl der benötigten Logikgatter angeht.

Sowohl für die Darstellung von Texturfarben, als auch für Beleuchtungsberechnungen, wird innerhalb der GPUs das RGB-Format genutzt. Die Truecolor-Darstellung – 24 Bit, jeweils 8 für R, G und B – gilt heute noch als gut genug. Truecolor ist bei näherer Betrachtung für die Berechnung realistischer Bilder jedoch viel eingeschränkter, als man zunächst denkt. Deshalb betrachten wir heute HDR-Rendering. Dabei klären wir auch, was HDR-Rendering heute schon bringen kann, wo aktuelle Monitore nur niedrige Dynamik unterstützen.


   Beleuchtung mit Vertexshading

Man könnte die Vorteile, ja Notwendigkeit vom HDR-Lighting in wenigen Sätzen beschreiben. Doch wir möchten das Thema nicht losgelöst betrachten, sondern in den Kontext einbetten. Dazu betrachten wir zunächst einige traditionelle Beleuchtungsverfahren – welche durch HDR-Lighting nicht ersetzt, aber erweitert werden.

Die GPU rendert Polygonzüge, die jeweils aus Dreiecken zusammengesetzt sind. Die Geometriedaten werden in Vertices und den richtigen Verbindungsinformationen der Grafikkarte übergeben; vorher stellt die CPU ein, wie (aus welchem Winkel, in welcher Größe, in welcher Lage) die Geometrie dargestellt werden soll. Pro Vertex, also Eckpunkt, liegt nicht nur die 3D-Koordinate vor. Weitere Angaben sind:

  • Materialfarbe: Man kann somit auch ganz ohne Texturen arbeiten und trotzdem farbige Szenen rendern.

  • Normalenvektor: Dies ist eine Winkelangabe und gibt die Ausrichtung des Eckpunktes an. Hat man nur einen Punkt im Raum, kann man schließlich nicht wissen, wie er im Vergleich zu seinen Umgebungspunkten liegt (ob zum Beispiel mitten in einer Ebene oder an einem Abhang), deshalb nutzt man vorberechnete Normalenvektoren. Für Beleuchtungberechnungen muss schließlich bekannt sein, ob der Eckpunkt der Lichtquelle zu- oder abgeneigt ist.

Traditionell unterscheidet man bei Beleuchtungsberechnungen zwischen drei Komponenten:

  • Ambient Light: Hierbei handelt es sich um Licht, das von keiner speziellen Quelle kommt und überall gleichmäßig stark vorhanden ist. Mit Ambient Light kann man Umgebungslicht simulieren.

  • Diffuse Light: Normales Licht, was von einer punktförmigen Quelle ausstrahlt. Diffuse Light wird traditionell mittels Gouraud-Shading realisiert. Gouraud-Shading berechnet die tatsächliche Lichtwirkung pro Eckpunkt eines Dreiecks und interpoliert die Werte über die Dreiecksfläche. In der Regel dunkelt man mit Gouraud-Shading die Materialfarbe ab, daher auch der Begriff "Shading". Dies ist bitte nicht zu verwechseln mit Schattenwurf-Berechnungen, das wäre dann "Shadow-Casting".

  • Specular Light: Verantwortlich für Glanzeffekte. Specular Light hellt die Materialfarbe auf, reflektiert wird das Licht aber nur in einem engen Winkel, ganz im Gegensatz zum Diffuse Light, welches auf dem Material diffus in alle Richtungen streut. Specular Lighting wird in vielen Spielen nicht genutzt.

Das Gesamtlicht berechnet sich aus Ambient Light + Diffuse Light + Specular Light. Das Licht, welches auch farbig sein darf, wird dann mit der Materialfarbe multipliziert (ohne Licht sieht man ja nichts, dann muss alles schwarz werden). Wie die Materialfarbe mit der Textur kombiniert wird, stellt der Entwickler ein. In der Regel dominiert die Basemap, also die bildgebende Textur, die Erscheinung des Polygons. Die Beleuchtung sorgt oft nur für einen sanften Helligkeitsverlauf – man hat verschiedene "Shades". "Shading" hat also wirklich nichts mit Schattenwurf zu tun.


   Beleuchtung mit Lightmaps

Die geometrische Auflösung reicht oft nicht aus, um realistische Schattierungen zu erzeugen. Noch schwieriger ist der Schattenwurf. Gerade weil die 3D-Szene auf eine 2D-Ausgabe abgebildet wird, benötigen wir Schatten, um Entfernungen abschätzen zu können. Schattenwurfberechnung erfordert extreme CPU-Leistung. Daher ist es üblich, wo es nur geht auf dynamischen Schattenwurf zu verzichten, und die statische Lichtumgebung inklusive den Schatten in Lightmaps vorzurendern.

Das heißt, für jede Oberfläche wird eine spezielle Textur berechnet, welche in der Regel nur Graustufen speichert. Diese Graustufen werden mit der beleuchteten Basemap multipliziert. Normale Texturen speichern nur Werte zwischen Null und Eins, mit Lightmaps dunkelt man demzufolge immer ab (für Aufhellungen müsste man mit Werten größer 1 multiplizieren).

Für Lightmaps reicht oft eine extrem geringe räumliche Auflösung. Im Zusammenhang mit bilinearer Filterung, welche bei Vergrößerung für starke Unschärfe in der vergrößerten Textur sorgt, simuliert man gleich das Streulicht, welches in der Realität scharfe Schattenränder verhindert. Außerdem nutzen unbunte Lightmaps in der Regel nur einen Kanal (die Grundhelligkeit) und nehmen insgesamt nicht viel Platz im Grafikkartenspeicher weg. Bei farbigen Lightmaps bleibt immerhin der Vorteil der geringen Auflösung.

Wegen der geringen Auflösung von Lightmaps reicht meistens der reine bilineare Filter. Damit kostet Lightmapping gerade mal einen Takt. Dynamische Lightmaps, insbesonders wenn sie farbig sind (wie zum Beispiel in Unreal zu bewundern), belasten die CPU und das gesamte Computer-System stark. Denn alles was bei Lightmaps dynamisch ist, wird dann wieder zur CPU-Arbeit.


   Beleuchtung mit Pixelshading

Lightmapping ist nur performant, wenn man vorberechnete Lightmaps nutzt, welche nur statisches Licht simulieren können. Vertexshading ist hingegen dynamisch. Könnte man sich die Verwendung von sehr fein aufgelöster Geometrie erlauben, wäre man in Fragen der Beleuchtungs-Detailstufe aus dem Schneider.

Zwar ist die Vertexpower heutiger Grafikkarten sehr hoch, aber zu kleine Dreiecke machen das Rendern ineffizient. Der Pixelteil ist traditionell darauf optimiert, große Dreiecke schnell zu füllen und sich nicht mit Fitzel-Polygonen herumzuschlagen. Das verhindert unter anderem, dass sich Specular Lighting beim Vertexshading sinnvoll einsetzen lässt, denn die Simulation eines Glanzpunkt-Effektes wirkt nur bei sehr feiner Geometrieauflösung gut.

Als Verfeinerung zum Vertexshading lässt sich Pixelshading verwenden. Anstatt wie beim Gouraud-Shading pro Eckpunkt die Lichteinwirkung zu berechnen und über das Dreieck zu interpolieren, wird die Normale über das Dreieck interpoliert und die Lichtintensität pro einzelnem Pixel neu berechnet. Hierfür benötigt man die DP3-Operation, die einige DirectX7-Karten bereits im Combiner anbieten, und welche seit DirectX8 in jeder Pixelshader-Version geboten werden muss. Aus Sicht der Beleuchtungsberechnung haben wir es nun mit runden und nicht mehr flachen Dreiecksflächen zu tun – das Shading wird realistischer, und Specular Lighting zur Simulation glänzender Oberflächen sinnvoll.

In DirectX8 ist für Farb-Operationen mindestens ein vorzeichenbehaftetes 9-Bit-Format pro RGB-Kanal vorgeschrieben. Das heißt, man hat die üblichen 8 Bit, welche den Raum von 0 bis 1 repräsentieren, und das Vorzeichen. Aufgrund der Vorzeichendarstellung im so genannten Zweierkomplement reicht der intern im Pixelshader nutzbare Farbraum von -1,003 bis 1,000.

Man darf auch mit Formaten rechnen, welche einen größeren Umfang darstellen. Die Radeon 8500 erlaubt zum Beispiel Werte bis 8,000. Mit dem Bereich bis nur 1,000 ist man stärker eingeschränkt, als man zunächst denken mag. Der naheliegenste Gedanke wäre ja: Da es sowieso keine Farbe heller als weiß gibt, reicht eine Darstellung bis 1 aus. Doch für Normalisierungs-Operationen benötigt man einen größeren Zahlenraum. Warum für hochwertige Grafik eine Normalisierung der interpolierten Normalen notwendig ist, haben wir bereits in einem früheren Artikel gezeigt.

Man kann auch in DirectX8 renormalisieren, doch nur über den Umweg mit einem komplizierten Texturzugriff. Schöner für den Entwickler wäre natürlich eine einheitliche Programmierung.


   Der Sinn von HDR-Rendering

Genau hier setzt High Dynamic Range-Rendering an: Vereinheitlichte Programmierung. Mit dem Shader Model 3.0 wurde zum Beispiel der Befehlssatz für Pixel- und Vertexshader fast vollständig vereinheitlicht. HDR-Rendering hat ansich aber nichts mit SM3 zu tun, es fällt nur (mehr oder minder zufällig) mit dem Aufkommen von SM3-Karten zusammen.

Mittels HDR-Rendering kann man sich viele Tricks ersparen und stattdessen die Beleuchtung "wirklich ausrechnen" (die Anführungszeichen sollen auf die weiterhin verwendeten groben Näherungsformeln hinweisen). Mittels dynamischem HDR-Rendering lässt sich auch die Einstellung unserer Pupille auf die Gesamthelligkeit simulieren. Folgende drei Beispiele sollen den Sinn vom HDR-Rendering verdeutlichen.

  Der Übergang von einer Tageslicht-Szene in einen dunklen Keller

Der Keller ist sehr, sehr viel dunkler als eine von der Sonne bestrahle weiß verputze Hauswand. Die Kellerwände müssen also im Framebuffer mit sehr geringen Helligkeiten gespeichert werden. Da bleiben beim Truecolor-Format nur ganz wenige Bits, entsprechend wenig Abstufungen. Hellt man die Szene beim herkömmlichem Rendering auf, um die Adaption des Auges zu simulieren, sieht man nur grobe Blöcke – denn für feinere Abstufungen reicht die Truecolor-Helligkeitsauflösung nicht. Ähnliches kann man beobachten, wenn der Anwender in dunklen Szenen die Gamma-Korrektur hochreißt: Zwar wird die Textur heller, doch die neu sichtbaren Details sind äußert spärlich. Stattdessen dominieren hässliche Colorbanding-Artefakte. Mittels dynamischem HDR-Rendering würde das Bild automatisch heller, und wäre trotzdem noch detailreich.

Eine reine "Dunkel-Simulation", à la Doom 3, kann natürlich passenden Content verwenden. Doch auch hier fehlt die Simulation der Adaption des Auges.

  Der Übergang von einer Dunkelszene ins Helle

Wer kennt das nicht: Man verlässt einen dunklen Raum und geht in die pralle Sonne – und kneift erst einmal die Augen zu. Viel erkennt man draußen zunächst nicht, alles wirkt überstrahlt. Schon mittels herkömmlichem Rendering ist das im Prinzip realisierbar – siehe den "Fullscreen-Glow-Effekt" bei World of Warcraft. Doch jener Effekt ist leider nicht adaptiv: Solange der Fullscreen-Glow aktiviert ist, wird in WoW immer überstrahlt - auch dann, wenn sich das Auge längst an die Sonne gewöhnt haben müsste.

Mit HDR-Rendering wäre eine allmähliche Augenanpassung realisierbar. Im gleichen Zuge könnte man dafür sorgen, dass extrem helle Objekte einen Strahlenkranz zeigen. Diese eine Sache wird landläufig als "HDR" gesehen. Dabei ist das nur ein Baustein, der beim adaptiven HDR-Rendering zusätzlich integrierbar ist. HDR-Rendering per se funktioniert auch ohne Überstrahl-Effekt.

  Objekte mit Schattenwurf unter Tageslicht

Eine von der Sonne angestrahlte Wolke ist sehr, sehr viel heller als eine im tiefen Schatten befindliche asphaltierte Straße. Will man in einem Frame beides gleichzeitig darstellen, muss man ohne HDR-Rendering tricksen. Traditionell wird statische Beleuchtung verwendet, das heißt die Texturen und vorgefertigten Lightmaps werden so, wie sie sind, genutzt. Sollen bewegliche oder in ihrer Helligkeit veränderliche Lichtquellen ins Spiel kommen, wird es schwierig, da man für alle Situationen den passenden Content vorrätig haben müsste.

Dann sucht man den Kompromiss zwischen falsch berechneten Helligkeiten (z. B. zu dunklen Wolken oder zu hellen Straßen im Schatten) und ausreichender Präzision (z. B. völlig "weiß zugelaufenen" Wolken und einer eintönig dunkelgrauen Straße, auf der man unrealistischerweise im Grau keine Details mehr sieht). Oder man verzichtet eben darauf, sehr helle Lichtquellen realistisch wirken zu lassen. Mit HDR-Rendering lässt sich die Blende der virtuellen Kamera so adjustieren, dass alle Bereiche detailreich erkennbar bleiben.






Kommentare, Meinungen, Kritiken können ins Forum geschrieben werden - Registrierung ist nicht notwendig Weiter / Next

Shortcuts
nach oben