
von Mirko Hänßgen
Grau ist out: Tipps und Tricks zur Generierung von Normalmaps
Wenn man sich einmal die Spieleknüller der letzten Jahre, wie „Doom III“ oder „Farcry“, aber auch kommende Projekte, wie zum Beispiel „Unreal Tournament 2007“ oder „Project Offset“ anschaut, wird immer deutlicher, dass Normalmaps längst zu einem festen Bestandteil in heutigen Spieletiteln geworden sind. Allerdings eignen sich Normalmaps nicht nur für Realtime-Anwendungen, sie helfen auch dem Anwender Polygone einzusparen und trotzdem enorm detaillierte Oberflächen zu simulieren.
Nicht zuletzt weil Cinema 4D ab der Version 9.5 die Generierung und Ausgabe von Normalmaps unterstützt und weil es einige signifikante Unterschiede zu Bumpmaps gibt, soll dieser Artikel das für Cinema-User noch relativ neue Terrain etwas erschließen helfen.
Obwohl es mittlerweile sehr viele gute Tutorials gibt, die erklären, wie Normalmaps erstellt werden, soll hier in aller Kürze nochmals erklärt werden, warum soviel Wind um dieses Thema gemacht wird.
Besinnt man sich auf das normale „Grayscale Image“, aus welchem man die typische „Bumpmap“ –also die Tiefeninformation anhand der Helligkeit von Weiß bzw. Schwarztönen, ergo Graustufen- erzeugt um Dellen oder Erhebungen zu simulieren, stellt man fest, dass der Farbraum, der uns zur Verfügung steht um diese Erhebungen darzustellen 2^8, also 256 Farben, enthält. Auf den ersten Blick eine große Menge, zumal die wenigsten sicher alle 256 Grautöne unterscheiden könnten, allerdings stößt man in diesem Bereich schnell an Grenzen., besonders, wenn man filigrane Strukturen mit unterschiedlichen, eng beieinander liegenden Höhen und Tiefen darstellen möchte.

Das Normalenrelief geht da einen anderen Weg statt den ursprünglichen 256 Farben stehen nun 16,7 Millionen Farben ((24 Bit) + ein Alphakanal (8 Bit)) = 32 Bit) für die farbige Codierung der „Höhenstufen“ bereit. Dabei entspricht jedoch nicht wie bei einem Grayscale Image eine Farbe einer Höhenstufe.
Entscheidend ist hier nur der Winkel der Normale der Fläche zum Weltkoordinaten- ursprung, zum lokalen Koordinatenursprung oder zu einer Tangente an der Oberfläche des Zielobjektes, letztere ist die am meisten in Realtime-Anwendungen genutzte Art und Weise und auf diese wird im gesamten Artikel eingegangen. Wem das jetzt alles zu mathematisch klang, der schaue sich Bild 01 und 02 im Vergleich an:

Bei der Bumpmap kann man verschiedene Höhenstufen ausmachen, wodurch im Modell eine Art Treppeneffekt zustande zu kommen scheint. Würde man im Normalenrelief, wie beim Graustufenbild nur die Farbe der Stufen beachten, schienen beide auf einer Ebene zu liegen, die lediglich durch „farbige Ränder“ abgegrenzt würden. Diese bunten Ränder, und nur die, erzeugen jedoch in diesem Fall die Illusion von Höhe, ist der Anstieg und die Ausrichtung der Normale, wie zum Beispiel an den Seiten gleich, bleibt auch die Farbe gleich, sobald unsere Stufe aber einen 90° Bogen beschreibt, ändert sich kontinuierlich die Farbe, da sich die Normalenausrichtung der Flächen entlang dieser 90° ändert.
Um die Technik zu begreifen, verweise ich, auf den sehr guten englisch sprachigen Artikel zum Thema Normalmaps mit Cinema 4D ab Version acht:
Uns geht es aber jetzt darum Fehler zu vermeiden, die häufigsten Anwendungsfehler sind hier zusammengetragen:
Normalmaps sind Flachreliefs, keine räumlichen Gebilde
Man ist nach den ersten Versuchen und befriedigenden Ergebnissen sehr schnell versucht, möglichst viel, oder alles, was sich an Detail auf einem Objekt befindet, in eine Normalmap zu baken, doch sollte man immer bedenken, dass für Normalmaps, wie für Bump- und Displacement-Maps natürlich auch, gilt, dass nur das wiedergegeben wird, was von oben sichtbar ist. Ein übertriebenes Beispiel, was natürlich nicht die gewünschten Ergebnisse erzielt, ist in Bild 05 zu sehen. Ein Helm soll als Normalmap ausgegeben werden.

Deshalb sollte man sich vorher gut überlegen, wie die Elemente auf der Lowpoly Zielgeometrie angeordnet werden sollen und dass diese Elemente nicht mit zu großen Höhenunterschieden zum Lowpolymesh versehen werden sollten, wenn man sie anschließend komplett über eine Normalmap darstellen will.
Was bei solchen Problemen helfen kann, ist die bei Normalmaps wichtige Faustregel, dass, alles Abschrägungen besitzen muss. Wie auf Bild 01 und 03 dargestellt, wird bei Bumpmaps die Höheninformation über die Grauwerte erzeugt. Da bei Normalmaps aber der Anstieg eine Rolle spielt, würde die Vektorinformation der Normale einer senkrechten Fläche (Bild 07: roter Pfeil) sofort von der darüberliegenden, und die gibt es immer, sonst wäre das Polygon zweidimensional und würde nicht dargestellt, (grüner Pfeil) überschrieben. Wenn diese Fläche parallel zur Zielgeometrie und zudem noch planar ist, würde der Anstieg 0 betragen und die Farbe würde blau (128, 128, 255) bleiben, in diesem Fall (s.h. Bild 07) wie der planare Untergrund, auf dem das Objekt steht, man würde also keinerlei Erhebung sehen, obwohl sie existiert (s.h. Bild 08). Das ist übrigens auch der Grund, warum das Design von „Doom III“ sehr „gebevelt“ aussieht.

Bild 07: Die Information der Normalenausrichtung für den roten Pfeil wird von der des darüberliegenden grünen Pfeils überschrieben. In seltenen Fällen, werden statt des grünen Pfeils, die Information der Normalenausrichtung des blauen Pfeils verwendet, welche nur als eine sehr schmale Objektkante in der Normalmap ausgegeben würden.

„Meshsplitting“
Ein weiterer wichtiger Punkt ist, dass man kritische Stellen in separate Maps rendern kann und die Dateien später in Photoshop o.ä. wieder zu einer einzigen zusammenfügt. Damit ist folgendes gemeint: Hat man ein komplexes Modell, was nicht durchgängig, resp. aus unterschiedlichen Teilstücken zusammen gesetzt ist und möchte man dieses auf eine Lowpolygeometrie übertragen, so ist es besser diese Teilstücke des Highpolymodels für das endgültige Lowpolymodel getrennt zu berechnen.

Bild 12: Um einer Überlappung von Hornansatz und Helm entgegen zu wirken, wurde das Mesh geteilt, die Normalmap getrennt in zwei Dateien erzeugt und anschließend wieder zusammengefügt.
Dies bedeutet zwar höheren Aufwand, kann aber zu saubereren Ergebnissen in der Normalmap führen, als dies ohne Zerteilung der Fall gewesen wäre. Der Grund ist, dass die Normalmap-Berechnung an kritischen Stellen nicht immer eindeutig ausgeführt werden kann, überlappt sich die Geometrie des Highpolymeshes in einem Punkt beispielsweise, was übrigens vermieden werden sollte, kann es zu einer fehlerhaften Darstellung kommen, es ist sogar möglich, dass es zu einer Invertierung der Normale an der Stelle führt. Um dieses Problem zu umgehen, splittet man das Highpolymesh auf, um die zwei getrennt berechneten Dateien später wieder zu vereinigen und auf das gesamte Lowpolymesh anzuwenden.
Höhen und Tiefen
Besonders am Anfang sind Normalmaps schwer zu „lesen“. Für manche kann es so aussehen als wäre die Map invertiert, allerdings gewöhnt man sich rasch an die außergewöhnliche Farbgebung.

Bild 13: Wird das Ergebnis jetzt als Höhe oder doch als Tiefe interpretiert?
Zu Normalmaps die an einer Tangente an der Oberfläche des Zielobjektes erzeugt werden sowie in Bild 013, lässt sich folgendes sagen: In vertikaler Richtung steht türkis (128,255,255) für einen Anstieg der Flächen und lila (128, 0, 255) für einen Abstieg der Flächen. Horizontal haben wir blau (0, 128, 255) für einen Anstieg und rosa (255, 128, 255) für einen Abstieg. Dazwischen lassen sich natürlich, wie in einem Farbspektrum weitere Farben einfügen, wodurch das Ergebnis, je mehr Farbnuancen der einzelnen „Hauptfarben“ (türkis, lila, blau und rosa) auftreten, „runder“ erscheint.
Unser Beispiel aus Bild 13 zeigt somit eine Höhe, in der sich drei Kreise als Vertiefung befinden.
Wie man sieht, kann man sich die oben beschriebene Farbeigenschaft zu Nutze machen. Hat man eine Normalmap für ein Objekt erzeugt, und stellt fest, dass es besser wäre, beispielsweise, alle Höhen zu Tiefen zu konvertieren und umgekehrt, so dreht man die Normalmap einfach um 180° (Bild014) und man erhält das gleiche Ergebnis, das man erhalten würde, wenn man eine Bumpmap invertiert.

Invertieren von Normalmaps
Zu aller erst: Es ist NICHT ratsam, Normalmaps zu invertieren um ihr Ergebnis umzukehren, wie schon gesagt, muss man sie lediglich drehen. Eine invertierte Normalmap wird die Information beinhalten, dass die Normale der Fläche in die entgegengesetzte Richtung zeigt, und somit wird man an dieser Stelle nichts außer einem schwarzen Bereich sehen können. Dennoch kann man auch aus dieser Eigenschaft Vorteile ziehen. So setzt beispielsweise id-Software die Umkehrung der Normalmap bei Löchern und Ähnlichem, in dem „Licht verschwindet“, ein. Zunächst wird die Normalmap nach herkömmlichen Mitteln erzeugt, dann werden die Bereiche, die später schwarz erscheinen sollen markiert daraufhin wird anschließend in einem Grafikprogramm die Farbe invertiert.

Natürlich könnte man das Problem auch über einen schwarzen Kreis in der „Specularmap“ lösen, aber nicht immer macht man sich die Mühe, oder hat die technischen Möglichkeiten, wenn es sich beispielsweise um ein Gameprojekt handelt, einen „Specularity-Channel“ explizit zu definieren. Über die Normaleninvertierung kann man sich das Leben in dieser Hinsicht ein bisschen erleichtern.
Spiegeln verboten, Drehen erlaubt
Was das Spiegeln von Normalmaps angeht: Don’t do it!
Ich habe viele Bilder gesehen, die mit Hilfe von ziemlich aufwendigen Normalenreliefs generiert wurden, aber das Endergebnis wurde dadurch getrübt, dass das Mesh gespiegelt wurde, wobei die Informationen in der Normalmap nur für eine Seite galten. Seltsamer Weise, passiert der Fehler sogar Profis, obwohl er offensichtlich ist: Erzeugt man ein Mesh, kann man, um Texturspeicher zu sparen, wenn das Mesh auf beiden Seiten symmetrisch ist, normalerweise einfach die UVs für eine Seite mappen und anschließend das ganze Mesh an seiner Mittelachse spiegeln. Die UVs überlagern sich daraufhin in der Textur. Für Farbe, Glanz und Ähnliches funktioniert das auch, sobald man aber ein Normalenrelief ins Spiel bringt, scheitert diese Technik aus dem einfachen Grund, weil die Normalenfärbung auf der rechten und linken Seite des Objektes nicht gleich ist.

Betrachtet man sich die Normalentextur für den Helm aus Bild 17, so fällt auf, dass sich die Farbcodierung links und rechts unterscheidet. Das ist auch gut so, denn im Prinzip kommt hier wieder das zum Tragen, was weiter oben schon einmal erklärt wurde, blau entspricht einem Anstieg, rosa einem Abstieg und so weiter. Auf dem Helm sind durch diese Farbcodierungen die Erhebungen eindeutig definiert. Hätte man die rechte Seite jedoch gespiegelt, hätte man links einen Abstieg, wo eigentlich ein Anstieg hätte sein müssen, und das würde dazu führen, dass die Höheninformation der gespiegelten Seite umgekehrt wird, aus den Höhen werden Tiefen usw. Manchmal, wenn man Glück hat, (oder nicht, wie man es eben sieht) fällt es nicht weiter auf, aber spätestens, wenn man diesen Fakt bei einem Charakter mit einem faltigen Gesicht, und vielen Kleidungsdetails wie Erhebungen etc. ignoriert, wird man auf erhebliche Probleme stoßen.
Um eben genau das zu vermeiden, empfiehlt es sich das Objekt als ganzes zu mappen und nicht nur Teile davon. Wobei man sich vorher überlegen sollte, ob es vielleicht nicht sogar Teile gibt, die man durch einfaches Drehen um die Mitte des Meshs auf die andere Seite bringen kann: Diese Texturplatz sparende Technik funktioniert zum Beispiel bei Objekten, wie einem Ventilator: Man modelliert nur einen Flügel und mappt diesen in die Normalmap, danach kann man Kopien des Flügels an der Mitte des Ventilators drehen, ohne sich dabei Sorgen um die Normalenausrichtung machen zu müssen, das Relief wird weiterhin korrekt dargestellt. Die UVs der Flügel würden in der Textur übereinander liegen, somit hätten alle die selbe Normalenausrichtung, der „Spiegelungsfehler“ tritt jedoch nicht auf, da die Objekte lediglich gedreht wurden. Ergo: Spiegeln verboten, Drehen erlaubt.
Falls sich einige fragen, ob das nicht ein Widerspruch zum oben beschriebenen Fakt ist, dass eine Normalmap um 180° gedreht, umgekehrt wird, ist das berechtigt. Allerdings drehen wir in dem Fall nicht die Normalmap, sondern nur das Objekt, auf welchem sich die Normalmap befindet, die UVs bleiben davon gänzlich unbeeindruckt, spiegeln wir dieses Objekt jedoch, gelten für die UVs die gespiegelten Koordinaten und das führt zu falschen Ergebnissen.
Lichtsetup?
Ab und zu taucht die Frage auf, was man für Lichteinstellung für Normalmaps wählen muss, wenn man etwas in eine Textur baken will. Um es kurz zu machen, es ist vollkommen egal. Da sich Normalmaps nur an der Geometrie und nicht am Licht orientieren spielt das keine Rolle.
Ein Wort zu den Formaten
Abschließend noch ein Wort zum Dateiformat, in dem die Normalmap abgespeichert wird. Es ist nicht ratsam die Normalmap als JPG abzuspeichern, da aufgrund der JPG-Kompression Artefakte in der Map entstehen, Manchmal ist das beispielsweise in Diffusemaps, wo Haut mit vielen Unebenheiten dargestellt wird nicht allzu tragisch, in einer Normalmap ist es jedoch ein großes Problem. Die Standardfarbe, mit der ebene Oberflächen dargestellt werden ist RGB (128, 128, 255) sobald einer dieser Farbwerte auch nur um eine Stelle abweicht, wird das Relief für diesen Bereich anders schattiert. Das sollte man nicht ignorieren, da es, gerade bei kachelbaren, randlosen, Normalmaps, unglaublich wichtig ist, dass alle Farben an den Rändern jeweils horizontal und vertikal absolut identisch sind. Sobald Artefakte auftauchen, werden in den Reliefs ungewollte Schattierungen erzeugt. Um sich diesen Frust zu ersparen sollte man seine Normalmaps in Formaten wie TGA oder PSD abspeichern, das führt zwar zu größeren Dateien, aber auch zu sauberen Reliefs.
Somit sollten einige Stolpersteine aus dem Weg geräumt, oder zumindest mit fettem roten Absperrband markiert worden sein. Normalmaps muss man nicht mit Skepsis begegnen, da sie eine echte Bereicherung für jeden, der hochauflösende Reliefs benötigt, sind.
Noch einige wichtige Links, die man nicht unbeachtet lassen sollte, wenn man sich mit dem Thema näher auseinander setzen möchte:
http://developer.nvidia.com/object/photoshop_dds_plugins.html Ein völlig freies Tool von Nvidia zur Konvertierung von Graustufenmaps in Normalmaps, eine große Erleichterung, wenn man viele kleine Details in Normalmaps zeichnen muss. (Achtung: im Deutschen Photoshop müssen beide Plug-Ins, aus dem erzeugten Plug-In Ordner im Photoshopverzeichnis in das Verzeichnis: Zusatzmodule\Effekte verschoben werden, ansonsten lässt sich der Filter nicht verwenden)
http://www.poopinmymouth.com/tutorial/normal_workflow.htm Ein englisch sprachiges Tutorial leider für 3DS Max, aber es sind einige nützliche Tipps enthalten.
http://members.shaw.ca/jimht03/normal.html Artikel über die Technik von Normalmaps für Cinema 4D
http://www.tools4d.com/ unter Free Plugins kann man sich kostenlos Paul Everetts ZPainter zur Generierung von Normalenreliefs in Cinema herunterladen.
Mirko Hänßgen