Antworten:
Die Farben in einer normalen Karte repräsentieren die Normalen an jedem Punkt. Wenn ein normal ist (x, y, z)
, wird der entsprechende Bildpunkt in der normalen Karte haben jeweils x
, y
und z
aus dem Bereich zugeordnet , (-1,1)
um (0,255)
auf die roten, grünen zu erhalten und Blau - Komponenten sind.
Jetzt wird die z-Achse typischerweise als Richtung von der Oberfläche weg verwendet. Eine perfekt ebene Fläche, so Normalen am (0, 0, 1)
ganzen Körper , hat x
und y
beide abgebildet 128
und z
abgebildet 255
. Das heißt, die resultierende Farbe ist (128, 128, 255)
das Himmelblau, das Sie häufig in normalen Karten sehen.
Die Unebenheiten in einer Oberfläche weichen von dieser Normalität ab, entfernen ein wenig von der blauen Komponente und geben sie an die roten und / oder grünen Komponenten weiter (abhängig davon, in welche Richtung die Unebenheit zeigt). Im Allgemeinen sind die Unebenheiten in Oberflächen nicht besonders übertrieben, sodass die normale Karte größtenteils blau bleibt. Sie sehen Magentas und Cyan für die Unebenheiten entlang der x- und y-Achse.
Wenn Sie die normale Karte für eine Oberfläche mit starken Unebenheiten gefunden haben, z. B. eine normale Ziegelkarte , werden Sie feststellen, dass die Kanten sehr rot und grün sind.
(128, 128, 255)
, die das Hellblau ist, auf das Sie sich wahrscheinlich beziehen. Es ist auf halbem Weg zwischen blau (0, 0, 255)
und weiß (255, 255, 255)
. Ein Beispiel finden Sie in den Ecken dieses Bildes .
(0, 0, 1)
abgebildet (128, 128, 255)
.
Es ist wahr, dass viele normale Karten im Tangentenraum nur einen begrenzten Farbbereich haben. Normale Karten für den Objektraum oder den Weltraum hätten eine größere Farbpalette, aber wenn wir in unserem Spiel nur normale Karten für den Tangentenraum verwenden (wie die meisten Entwickler), ist es eine rechtmäßige Frage, warum wir dies nicht tun. t Wählen Sie eine Codierung, die außerhalb des Bereichs liegt, den wir nicht verwenden, um mehr Präzision zu erzielen.
Anstatt beispielsweise [-1, 1] für jede Komponente [0, 1] zuzuordnen, könnten wir entscheiden, dass wir [-0,5, 0,5] für die XY-Komponenten [0, 1] und [0, 1] zuordnen. 0,5, 1] bis [0, 1] für die Z-Komponente. Das würde uns die doppelte Präzision geben.
Die Antwort ist, dass wir normalerweise keine höhere Präzision benötigen und die Verwendung der Standardzuordnung uns den Bereich gibt, in dem wir mit allen denkbaren Normalen umgehen können.
Manchmal brauchen wir jedoch mehr Präzision. Auf Oberflächen, die nahezu glatt, aber nicht ganz glatt sind und sehr subtile Unebenheiten aufweisen, kann die Kombination des Bereichs [-1, 1] plus DXT-Komprimierung aufgrund der schlechten Genauigkeit der Normalen durchaus zu sichtbaren Streifen führen. In Spielen, an denen ich gearbeitet habe, haben wir einen Parameter für die "normale Kartenstärke" pro Material hinzugefügt, mit dem Sie die Codierung für eine bestimmte Textur effektiv anpassen können, sodass Sie einen kleineren Bereich wie [-0,5, 0,5] oder [-0,1 verwenden können , 0.1] wenn Sie wollten, und dadurch viel präziser.
Ein Beispiel für die Art von Oberfläche, auf der wir dies verwenden würden, ist eine Motorhaube oder ein Glasfenster an der Seite eines Gebäudes (das nicht ganz flach, aber sehr leicht verzogen ist). Bei beiden handelt es sich um harte, glänzende Oberflächen mit einer recht subtilen Krümmung, was bedeutet, dass Sie aufgrund ihrer Auswirkung auf die Cubemap-Reflexionen leicht Unvollkommenheiten in den Normalen erkennen können. Durch Anpassen der normalen Kartencodierung für mehr Präzision wurde das Erscheinungsbild dieser Oberflächen erheblich verbessert.
Trotzdem waren sie eher die Ausnahme als die Regel, und die Standardcodierung [-1, 1] war für fast alle Oberflächen im Spiel völlig ausreichend.
Wer sagt, dass wir nicht? Sie beschränken Ihren Denkprozess auf Tangent Space Normal Maps, die (im Allgemeinen) immer von der Oberfläche weg zeigen, auf die sie abgebildet werden. Es gibt auch Normalkarten für den Welt- / Objektraum, die jede Farbe des Regenbogens enthalten, da sie nicht mit dem Koordinatenraum der Oberfläche zusammenhängen.
Als lustiges Experiment sollten Sie eine Tangentialraum-Normalkarte mit der TBN-Matrix multiplizieren und die resultierende Farbe anstelle der normalen Beleuchtung ausgeben. Beachten Sie, wie sich die Farben dramatisch ändern, da sie sich jetzt im Objektbereich befinden (oder im Ansichtsbereich, je nachdem, wie Sie Ihre TBN-Matrix erstellt haben).
Sie sind jedoch noch nicht fertig. Jetzt, da sich die Normalen im Objekt- / Ansichtsbereich befinden, werden Sie wahrscheinlich einige Vektoren mit negativen Werten haben. Sie müssen die Farben so vorspannen und skalieren, dass negative Werte die untere Hälfte des Farbraums und positive Werte die höhere einnehmen (wenn Sie die normale Karte tatsächlich korrekt darstellen möchten).
Wenn Sie das Experiment nicht selbst durchführen möchten, können Sie den Unterschied zwischen dem Weltraum und dem Tangentenraum im folgenden Bild sehen :
Normale Karten des Tangentenraums befinden sich in einem speziellen Koordinatenraum, der sicherstellt, dass positives Z immer normal zur Oberfläche ist. Da XYZ normalerweise in RGB codiert wird und die meisten Oberflächen relativ flach sind (z. B. dominiert das Punktprodukt zwischen der Normalen, die die Textur liefert, und einem Vektor, der die Oberfläche an einem beliebigen Punkt tangiert, ziemlich nahe bei 0), dominiert B den Farbraum im Tangentenraum.
Im Welt- / Objektraum gibt es keine dominante Farbe, aber diese normalen Karten möchten nicht deformiert werden. Wenn normale Karten des Tangentenraums verwendet werden, erfolgt die Beleuchtung entweder im Tangentenraum oder die normale Karte wird vor dem Beleuchten in einen Welt- / Ansichtsraum umgewandelt. Indem diese Transformation bis zur Renderzeit verschoben (oder ganz vermieden) wird, können Objekte gedreht und Texturkoordinaten deformiert werden, ohne die normale Karte zu ungültig zu machen. Normale Weltraumkarten sind normalerweise für die statische Weltgeometrie reserviert und können für den normalen G-Puffer in verzögerter Schattierung verwendet werden.
Sie können nur zwei Komponenten einer normalisierten normalen Karte in einer RG-Textur speichern und die dritte Komponente trivial neu berechnen. Ich weiß nicht, warum dies nicht häufiger vorkommt als der Leistungseinbruch der Quadratwurzeloperation.
1 = sqrt(x^2 + y^2 + z^2)
z^2 = 1 - x^2 - y^2
z = sqrt(1 - x^2 - y^2)
sqrt(1 - x^2 - y^2)
.
Wir verwenden tatsächlich die volle Farbtiefe.
Zunächst sollten Normalen eine Einheitslänge haben, andernfalls müssen wir eine teure (und unnötige) Renormierung im Fragment-Shader durchführen.
Nehmen wir an, Sie betrachten eine Textur wie in einem Bildeditor von vorne.
Für nur die sechs Hauptrichtungen (oben / unten / links / rechts / vorne / hinten) benötigen wir bereits Werte von 0, 128 und 255 in jedem der R-, G- und B-Kanäle. Sie sind offensichtlich nicht die einzigen 6 Richtungen, in die etwas zeigen kann, also brauchen wir auch Zwischenwerte. Das ist die volle Farbtiefe.
Der Grund, warum die meisten normalen Karten kreideblau sind, ist, dass sie meistens Normalen codieren, die auf den Betrachter zeigen (mein erster Aufzählungspunkt oben), und die meiste Zeit codieren sie Normalen, die mehr zeigen. oder weniger gegenüber dem Betrachter. Aber sie nicht haben , und ohne die volle Farbtiefe verwendet würden sie die Fähigkeit zu Punkt in jeder beliebigen Richtung verlieren.
Dies hat eigentlich nichts mit dem Begriff "Präzision" zu tun, sondern kommt nur aus der Richtung, in die Normalen zeigen, wenn sie in einer normalen Karte codiert werden.