
Parallaxenabbildung
Die
Parallax Mapping- Texturierungstechnik Àhnelt in ihrer Wirkung der
normalen Zuordnung , basiert jedoch auf einem anderen Prinzip. Die Ăhnlichkeit besteht darin, dass diese Technik wie das normale Mapping die visuelle KomplexitĂ€t und Detailgenauigkeit der OberflĂ€che mit der angewendeten Textur erheblich erhöht und gleichzeitig eine plausible Illusion des Vorhandenseins von Höhenunterschieden auf der OberflĂ€che erzeugt. Parallax Mapping funktioniert hervorragend in Verbindung mit Normal Mapping, um sehr zuverlĂ€ssige Ergebnisse zu erzielen: Die beschriebene Technik vermittelt den Reliefeffekt viel besser als Normal Mapping, und Normal Mapping ergĂ€nzt ihn fĂŒr eine plausible Simulation dynamischer Beleuchtung. Parallax Mapping kann kaum als eine Technik angesehen werden, die in direktem Zusammenhang mit Beleuchtungssimulationsmethoden steht. Dennoch habe ich diesen Abschnitt ausgewĂ€hlt, um dies zu berĂŒcksichtigen, da die Methode eine logische Weiterentwicklung der Ideen des normalen Mappings ist. Ich stelle auch fest, dass zum Parsen dieses Artikels ein gutes VerstĂ€ndnis des Normal Mapping-Algorithmus erforderlich ist, insbesondere des Konzepts des Tangentenraums oder des
Tangentenraums .
Die Parallaxenzuordnung gehört zur Familie der
Verschiebungszuordnungen oder geprÀgten Texturierungstechniken,
mit denen die Eckpunkte einer Geometrie basierend auf Werten versetzt werden, die in speziellen Texturabbildungen gespeichert sind. Stellen Sie sich zum Beispiel eine Ebene vor, die aus der GröĂenordnung von tausend Eckpunkten besteht. Jeder von ihnen kann entsprechend dem aus der Textur gelesenen Wert verschoben werden, der die Höhe der Ebene an einem bestimmten Punkt darstellt. Eine solche Textur, die die Höhenwerte in jedem Texel enthĂ€lt, wird als
Höhenkarte bezeichnet . Ein Beispiel fĂŒr eine solche Karte, die auf der Grundlage der geometrischen Eigenschaften der OberflĂ€che des Mauerwerks erhalten wurde, ist das folgende Bild:
Durch Abtasten aus dieser Karte und Verschieben jedes Scheitelpunkts gemÀà dem Höhenwert ist es möglich, eine konvexe OberflĂ€che aus einer idealen Ebene zu erhalten, die die geometrischen Parameter der ursprĂŒnglichen OberflĂ€che wiederholt. Wenn Sie also eine Ebene mit einer ausreichenden Anzahl von Scheitelpunkten nehmen und eine Höhenkarte aus dem Beispiel anwenden, erhalten Sie das folgende Ergebnis:

Der beschriebene Ansatz ist einfach und leicht zu implementieren, erfordert jedoch eine hohe Dichte an Eckpunkten im verarbeiteten Objekt, da sonst das Ergebnis der Verschiebung zu grob ist. Und wenn wir auf jeder ebenen FlÀche tausend oder mehr Eckpunkte freigeben, haben wir sehr bald einfach keine Zeit mehr, alles zu rendern, was wir brauchen. Vielleicht gibt es einen Algorithmus, mit dem Sie die QualitÀt des naiven Displacement Mapping-Algorithmus qualitativ simulieren können, ohne jedoch solche Geometriekosten zu verursachen? Wenn Sie stehen, setzen Sie sich, denn im Bild oben gibt es tatsÀchlich nur sechs Eckpunkte (zwei Dreiecke)! Das Relief des Mauerwerks wird dank der Verwendung von Parallax Mapping perfekt nachgeahmt, einer Relief-Texturierungstechnik, die nicht viele Eckpunkte erfordert, um das OberflÀchenrelief originalgetreu zu vermitteln, sondern wie Normal Mapping einen originellen Ansatz verwendet, um die Augen des Betrachters zu tÀuschen.
Die Hauptidee der Implementierung besteht darin, die Texturkoordinaten fĂŒr das aktuelle Fragment basierend auf der Blickrichtung und den Höhenkartendaten zu verzerren, um die Illusion zu erzeugen, dass dieses Fragment zu einem Teil der OberflĂ€che gehört, der höher oder niedriger liegt als er tatsĂ€chlich ist. Schauen Sie sich zum besseren VerstĂ€ndnis des Prinzips das Diagramm unseres Beispiels mit Ziegeln an:
Hier reprÀsentiert die raue rote Linie die Werte aus der Höhenkarte, die die geometrischen Eigenschaften der simulierten MauerwerksoberflÀche widerspiegeln. Vektor
colororange barV reprÀsentiert die Richtung von der OberflÀche zum Betrachter (
viewDir ). Wenn das Flugzeug wirklich geprĂ€gt wĂ€re, wĂŒrde der Betrachter einen Punkt auf der OberflĂ€che sehen
colorblueB . TatsÀchlich haben wir jedoch eine ideale Ebene und der Strahl in Blickrichtung kreuzt die Ebene an einem Punkt
colorgreenA das ist offensichtlich. Parallaxen-Mapping-Aufgabe zum Verschieben von Texturkoordinaten an einem Punkt
colorgreenA so dass sie mit den dem Punkt entsprechenden Koordinaten identisch werden
colorblueB . Weiter fĂŒr das aktuelle Fragment (entspricht dem Punkt
colorgreenA ) Wir verwenden die erhaltenen Koordinaten des Punktes
colorblueB Texturabtastung ist fĂŒr alle notwendig, was die Illusion erzeugt, dass der Betrachter einen Punkt sieht
colorblueB .
Die Hauptschwierigkeit liegt in der Berechnung der Texturkoordinaten eines Punktes
colorblueB am Punkt sein
colorgreenA . Parallax Mapping bietet eine ungefÀhre Lösung durch einfache Skalierung des Richtungsvektors von der OberflÀche
colororange barV an den Betrachter durch die Höhe des Fragments
colorgreenA . Das heiĂt, Ă€ndere einfach die LĂ€nge
colororange barV so dass es mit der StichprobengröĂe aus der Höhenkarte ĂŒbereinstimmt
colorgreenH(A) entsprechend dem Fragment
colorgreenA . Das folgende Diagramm zeigt das Ergebnis des Skalierungsvektors
colorbrown barP ::
Als nÀchstes der resultierende Vektor
colorbrown barP zerlegt in Komponenten gemÀà dem Koordinatensystem der Ebene selbst, die als Offsets fĂŒr die ursprĂŒnglichen Texturkoordinaten verwendet werden. DarĂŒber hinaus ist da der Vektor
colorbrown barP wird anhand des Werts aus der Höhenkarte berechnet. Je mehr der Höhenwert dem aktuellen Fragment entspricht, desto stĂ€rker ist der Versatz dafĂŒr.
Diese einfache Technik liefert in einigen FÀllen gute Ergebnisse, ist jedoch immer noch eine sehr grobe SchÀtzung der Position eines Punktes
colorblueB . Wenn die Höhenkarte Bereiche mit sich stark Àndernden Werten enthÀlt, wird das Ergebnis der Verschiebung falsch: höchstwahrscheinlich der Vektor
colorbrown barP Selbst in der NÀhe fÀllt nicht in die NÀhe des Punktes
colorblueB ::
Basierend auf dem oben Gesagten bleibt eine andere Frage: Wie kann man bestimmen, wie ein Vektor korrekt projiziert wird?
colorbrown barP zu einer willkĂŒrlich ausgerichteten OberflĂ€che, um Komponenten dazu zu bringen, Texturkoordinaten zu versetzen? Es wĂ€re schön, Berechnungen in einem bestimmten Koordinatensystem durchzufĂŒhren, in dem sich der Vektor ausdehnt
colorbrown barP auf den Komponenten wĂŒrden
x und
y immer der Basis des Texturkoordinatensystems entsprechen. Wenn Sie die Lektion ĂŒber
normales Mapping sorgfÀltig ausgearbeitet haben, haben Sie bereits vermutet, dass es sich um Berechnungen im Tangentenraum handelt.
Ăbertragen des Vektors von der OberflĂ€che zum Beobachter
colororange barV in den Tangentenraum erhalten wir einen modifizierten Vektor
colorbrown barP , deren Komponentenzerlegung immer in Ăbereinstimmung mit den Tangenten- und Bi-Tangentenvektoren fĂŒr eine gegebene OberflĂ€che durchgefĂŒhrt wird. Da die Tangente und die Bi-Tangente immer an den Achsen des Texturkoordinatensystems der OberflĂ€che ausgerichtet sind, können Sie unabhĂ€ngig von der Ausrichtung der OberflĂ€che die
x- und
y- Komponenten des Vektors sicher verwenden
colorbrown barP als Offsets fĂŒr Texturkoordinaten.
Die Theorie reicht jedoch aus, und nachdem wir die Ărmel hochgekrempelt haben, wenden wir uns der sofortigen Umsetzung zu.
Parallaxenabbildung
FĂŒr die Implementierung verwenden wir eine einfache Ebene mit Tangenten und Bias-Tangenten, die dafĂŒr berechnet wurden. Dies können wir bereits aus der Lektion ĂŒber die normale Zuordnung tun. Wir weisen Texturebenen eine Reihe von Ebenen zu:
diffuse ,
Normalen und
Offsets , von denen jede unter dem entsprechenden Link verfĂŒgbar ist. In der Lektion werden wir auch Normal Mapping verwenden, da Parallax Mapping die Illusion einer OberflĂ€chentopographie erzeugt, die leicht unterbrochen werden kann, wenn sich die Beleuchtung nicht entsprechend der Topographie Ă€ndert. Da normale Karten hĂ€ufig auf der Grundlage von Höhenkarten erstellt werden, gewĂ€hrleistet ihre kombinierte Verwendung die korrekte Verbindung der Beleuchtung unter BerĂŒcksichtigung des GelĂ€ndes.
Sie haben wahrscheinlich bereits bemerkt, dass die im obigen Link gezeigte Verschiebungskarte tatsĂ€chlich die Umkehrung der zu Beginn der Lektion gezeigten Karte ist. Die Implementierung von Parallax Mapping wird normalerweise mit solchen Karten durchgefĂŒhrt, die invers zu Höhenkarten sind -
Tiefenkarten . Dies geschieht, weil die Nachahmung der Aussparungen in der Ebene etwas einfacher ist als die Nachahmung der Höhe. Entsprechend dieser Ănderung Ă€ndert sich auch das Arbeitsschema Parallax Mapping:
Wieder sehen wir bekannte Punkte
colorgreenA und
colorblueB diesmal jedoch der Vektor
colorbrown barP erhalten durch Subtrahieren des Vektors
colororange barV von Texturkoordinaten an einem Punkt
colorgreenA . Tiefen statt Höhen können einfach durch Subtrahieren der Tiefenprobe von der Einheit oder durch Invertieren der Texturfarben in einem beliebigen Bildeditor erhalten werden.
Die Parallaxenzuordnung ist im Fragment-Shader implementiert, da die Höhendaten fĂŒr jedes Fragment innerhalb des Dreiecks unterschiedlich sind. Der Fragment-Shader-Code erfordert die Berechnung des Vektors vom Fragment zum Beobachter
colororange barV Daher wird es notwendig sein, ihm die Position des Fragments und des Beobachters im Tangentenraum zu vermitteln. Nach den Ergebnissen der Lektion "Normales Mapping" haben wir immer noch den Vertex-Shader in der Hand, der alle diese Vektoren bereits in den Tangentenraum ĂŒbertrĂ€gt. Wir werden ihn verwenden:
#version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aNormal; layout (location = 2) in vec2 aTexCoords; layout (location = 3) in vec3 aTangent; layout (location = 4) in vec3 aBitangent; out VS_OUT { vec3 FragPos; vec2 TexCoords; vec3 TangentLightPos; vec3 TangentViewPos; vec3 TangentFragPos; } vs_out; uniform mat4 projection; uniform mat4 view; uniform mat4 model; uniform vec3 lightPos; uniform vec3 viewPos; void main() { gl_Position = projection * view * model * vec4(aPos, 1.0); vs_out.FragPos = vec3(model * vec4(aPos, 1.0)); vs_out.TexCoords = aTexCoords; vec3 T = normalize(mat3(model) * aTangent); vec3 B = normalize(mat3(model) * aBitangent); vec3 N = normalize(mat3(model) * aNormal); mat3 TBN = transpose(mat3(T, B, N)); vs_out.TangentLightPos = TBN * lightPos; vs_out.TangentViewPos = TBN * viewPos; vs_out.TangentFragPos = TBN * vs_out.FragPos; }
Von den wichtigen Dingen
möchte ich nur bemerken, dass es speziell fĂŒr die Anforderungen der Parallaxenzuordnung erforderlich ist, den positionPoser im Tangentenraum auf den Fragment-Shader
aPos zu ĂŒbertragen .
Im Shader implementieren wir den Parallax Mapping-Algorithmus, der ungefĂ€hr so ââaussieht:
#version 330 core out vec4 FragColor; in VS_OUT { vec3 FragPos; vec2 TexCoords; vec3 TangentLightPos; vec3 TangentViewPos; vec3 TangentFragPos; } fs_in; uniform sampler2D diffuseMap; uniform sampler2D normalMap; uniform sampler2D depthMap; uniform float height_scale; vec2 ParallaxMapping(vec2 texCoords, vec3 viewDir); void main() { vec3 viewDir = normalize(fs_in.TangentViewPos - fs_in.TangentFragPos);
Wir haben die ParallaxMapping-Funktion angekĂŒndigt, die die Texturkoordinaten des Fragments und des Vektors vom Fragment zum Beobachter ĂŒbertrĂ€gt
colororange barV im tangentialen Raum. Das Ergebnis der Funktion sind versetzte Texturkoordinaten, die bereits fĂŒr Samples aus einer diffusen Textur und einer normalen Karte verwendet werden. Infolgedessen entsprechen die diffuse Farbe des Pixels und seine Normalen korrekt der geĂ€nderten âGeometrieâ der Ebene.
Was versteckt sich in der ParallaxMapping-Funktion?
vec2 ParallaxMapping(vec2 texCoords, vec3 viewDir) { float height = texture(depthMap, texCoords).r; vec2 p = viewDir.xy / viewDir.z * (height * height_scale); return texCoords - p; }
Diese relativ einfache Funktion ist eine wörtliche Implementierung der Methode, deren Hauptpunkte wir oben besprochen haben. TexCoords anfÀngliche Texturkoordinaten werden
genommen , mit deren Hilfe die Höhe (oder Tiefe)
ausgewÀhlt wird colorgreenH(A) from
depthMap fĂŒr das aktuelle Fragment. Den Vektor berechnen
colorbrown barP Der
viewDir- Vektor wird im Tangentenraum aufgenommen und das Paar seiner
x- und
y- Komponenten wird durch die
z- Komponente geteilt, und das Ergebnis wird durch den Leseversatzwert der
Höhe skaliert. Die height_scale-
Uniform wurde ebenfalls eingefĂŒhrt, um eine zusĂ€tzliche Kontrolle ĂŒber den Schweregrad des Parallax Mapping-Effekts zu ermöglichen, da der Verschiebungseffekt normalerweise zu stark ist. Um das Ergebnis zu erhalten, subtrahieren wir den resultierenden Vektor
colorbrown barP von den ursprĂŒnglichen Texturkoordinaten.
Wir werden uns mit dem Moment der Aufteilung von
viewDir.xy in
viewDir.z befassen . Da der Vektor
viewDir normalisiert ist, liegt seine Komponente
z im Intervall [0, 1]. Wenn der Vektor nahezu parallel zur OberflÀche der Komponente ist, ist
z nahe Null und die Divisionsoperation gibt den Vektor zurĂŒck
colorbrown barP viel lÀnger als wenn
viewDir nahe an der Senkrechten zur OberflÀche liegt. Mit anderen Worten, wir skalieren den Vektor
colorbrown barP so dass es zunimmt, wenn Sie die OberflÀche in einem Winkel betrachten - dies ermöglicht es Ihnen, in solchen FÀllen ein realistischeres Ergebnis zu erzielen.
Einige Entwickler ziehen es vor, die Skalierung durch Teilen durch
viewDir.z zu entfernen, da dieser Ansatz in bestimmten FĂ€llen aus einem bestimmten Blickwinkel zu falschen Ergebnissen fĂŒhrt. Diese Modifikation der Technik wird als
Parallaxen-Mapping mit Offset-Begrenzung bezeichnet . Die Wahl einer Ansatzoption bleibt gröĂtenteils eine Frage der persönlichen PrĂ€ferenz - zum Beispiel bin ich den Ergebnissen des ĂŒblichen Parallax Mapping-Algorithmus loyaler.
Die resultierenden verÀnderten Texturkoordinaten werden letztendlich verwendet, um aus der diffusen Karte und der normalen Karte auszuwÀhlen, was einen ziemlich guten OberflÀchenverzerrungseffekt ergibt (der Parameter
height_scale wird hier nahe 0,1 gewÀhlt):
Im Bild können Sie die Auswirkungen der Techniken Normal Mapping und Parallax Mapping vergleichen. Da Parallax Mapping OberflĂ€chenunregelmĂ€Ăigkeiten simuliert, sind bei dieser Technik Situationen möglich, in denen sich die Steine ââje nach Blickrichtung ĂŒberlappen.
Entlang der RĂ€nder der strukturierten Ebene sind auch seltsame Artefakte sichtbar. Sie treten aufgrund der Tatsache auf, dass die durch den Parallax Mapping-Algorithmus verschobenen Texturkoordinaten auĂerhalb des Einheitsintervalls liegen und je nach
UmhĂŒllungsmodus unerwĂŒnschte Ergebnisse verursachen können. Eine einfache Möglichkeit, solche Artefakte zu entfernen, besteht darin, einfach alle Fragmente zu verwerfen, fĂŒr die die Texturkoordinaten auĂerhalb des Einheitsintervalls liegen:
texCoords = ParallaxMapping(fs_in.TexCoords, viewDir); if(texCoords.x > 1.0 || texCoords.y > 1.0 || texCoords.x < 0.0 || texCoords.y < 0.0) discard;
Infolgedessen werden alle Fragmente mit verschobenen Texturkoordinaten, die aus dem Intervall [0, 1] herausfallen, verworfen und das Ergebnis der Parallaxen-Mapping-Aktion wird visuell akzeptabel. Offensichtlich ist diese ZurĂŒckweisungsmethode nicht universell und kann möglicherweise nicht auf einige OberflĂ€chen oder TexturierungsfĂ€lle angewendet werden. Am Beispiel eines Flugzeugs funktioniert es jedoch perfekt und trĂ€gt dazu bei, den Effekt der Ănderung des Reliefs des Flugzeugs zu verstĂ€rken:
Beispielquellen finden Sie
hier .
Es sieht gut aus und die Leistung der Methode ist ausgezeichnet - alles, was es brauchte, war eine zusĂ€tzliche Probe aus der Textur! Die Einfachheit der Methode hat jedoch erhebliche Nachteile: Der Reliefeffekt kann leicht zerstört werden, wenn die Ebene in einem Winkel betrachtet wird (was auch fĂŒr die normale Abbildung gilt) oder wenn Abschnitte in der Höhenkarte mit starken WertĂ€nderungen vorhanden sind:
Der Grund fĂŒr die Zerstörung der Illusion liegt in der Tatsache, dass der Algorithmus eine sehr grobe AnnĂ€herung an die reale Verschiebungsabbildung ist. Es können uns jedoch mehrere zusĂ€tzliche Tricks helfen, mit denen wir selbst bei Betrachtung eines Winkels oder bei Verwendung von Höhenkarten mit starken Ănderungen nahezu perfekte Ergebnisse erzielen können. Zum Beispiel können wir mehrere Beispiele aus einer Höhenkarte verwenden, um den Punkt zu finden, der dem Punkt am nĂ€chsten liegt
colorblueB .
Steiles Parallaxen-Mapping
Die Steep Parallax Mapping-Technik ist eine logische Weiterentwicklung des klassischen Parallax Mapping: Der gleiche Ansatz wird im Algorithmus verwendet, aber anstelle einer einzelnen Auswahl werden mehrere verwendet - zur besseren AnnÀherung des Vektors
colorbrown barP wird verwendet, um den Punkt zu berechnen
colorblueB . Aufgrund dieser zusÀtzlichen Abtastwerte ist das Ergebnis des Algorithmus visuell viel plausibler, selbst wenn scharfe Winkel zur OberflÀche betrachtet werden.
Die Grundlage des Steep PM-Ansatzes besteht darin, einen bestimmten Tiefenbereich in gleich groĂe Schichten zu unterteilen. Als nĂ€chstes durchlaufen wir die Ebenen und verschieben gleichzeitig die ursprĂŒnglichen Texturkoordinaten in Richtung des Vektors
colorbrown barP und Erstellen von Proben aus der Tiefenkarte, wobei in dem Moment angehalten wird, in dem die Tiefe der Probe geringer ist als die Tiefe der aktuellen Ebene. Schauen Sie sich das Diagramm an:
Wie Sie sehen können, bewegen wir uns von oben nach unten durch die Ebenen und vergleichen fĂŒr jede Ebene ihre Tiefe mit dem Wert aus der Tiefenkarte. Wenn die Ebenentiefe kleiner als der Wert aus der Tiefenkarte ist, bedeutet dies, dass der Vektor
colorbrown barP entsprechend dieser Schicht liegt ĂŒber der OberflĂ€che. Dieser Vorgang wird wiederholt, bis die Ebenentiefe gröĂer ist als die Auswahl aus der Tiefenkarte: in diesem Moment der Vektor
colorbrown barP zeigt auf einen Punkt unterhalb der simulierten OberflÀchentopographie.
Das Beispiel zeigt, dass die Auswahl aus der Tiefenkarte auf der zweiten Ebene (
D(2)=0,73 ) liegt immer noch "tiefer" in Bezug auf die Tiefe der zweiten Schicht gleich 0,4, was bedeutet, dass der Suchprozess fortgesetzt wird. Im nĂ€chsten Durchgang stellt sich heraus, dass eine Ebenentiefe von 0,6 âĂŒberâ dem Wert der Probe aus der Tiefenkarte liegt (
D(3)=0,37 ) Von hier schlieĂen wir, dass der Vektor
colorbrown barP FĂŒr die dritte Schicht wird die zuverlĂ€ssigste Position fĂŒr die verzerrte OberflĂ€chengeometrie erhalten. Sie können Texturkoordinaten verwenden
T3 abgeleitet vom Vektor
colorbrown barP , um die Texturkoordinaten des aktuellen Fragments zu versetzen. Offensichtlich wÀchst die Genauigkeit des Verfahrens mit der Anzahl der Schichten.
Ănderungen in der Implementierung wirken sich nur auf die ParallaxMapping-Funktion aus, da sie bereits alle Variablen enthĂ€lt, die fĂŒr die Funktionsweise des Algorithmus erforderlich sind:
vec2 ParallaxMapping(vec2 texCoords, vec3 viewDir) {
Zuerst initialisieren wir: Legen Sie die Anzahl der Ebenen fest, berechnen Sie die Tiefe jeder Ebene und ermitteln Sie schlieĂlich die GröĂe der Verschiebung der Texturkoordinaten entlang der Richtung des Vektors
colorbrown barP , die auf jeder Ebene verschoben werden mĂŒssen.
Als nĂ€chstes folgt eine Passage durch die Ebenen, beginnend von oben, bis eine Auswahl aus der Tiefenkarte gefunden wird, die âĂŒberâ dem Tiefenwert der aktuellen Ebene liegt:
In diesem Code durchlaufen wir alle Tiefenebenen und verschieben die ursprĂŒnglichen Texturkoordinaten, bis die Auswahl aus der Tiefenkarte geringer ist als die Tiefe der aktuellen Ebene. Der Versatz wird ausgefĂŒhrt, indem von den ursprĂŒnglichen Texturkoordinaten des Deltas basierend auf dem Vektor subtrahiert wird
colorbrown barP . Das Ergebnis des Algorithmus ist ein Versatzvektor von Texturkoordinaten, der mit viel gröĂerer Genauigkeit als die klassische Parallaxenabbildung definiert wird.
Mit etwa 10 Mustern wird das Mauerwerksbeispiel viel realistischer, selbst wenn es aus einem Winkel betrachtet wird. Das Beste ist jedoch, dass die Vorteile von Steep PM auf OberflĂ€chen mit einer Tiefenkarte sichtbar sind, deren Werte sich stark Ă€ndern. Zum Beispiel, wie bei diesem Holzspielzeug, das bereits frĂŒher demonstriert wurde:
Sie können den Algorithmus ein wenig weiter verbessern, wenn Sie die Funktionen der Parallax Mapping-Technik ein wenig analysieren. Wenn Sie die OberflĂ€che ungefĂ€hr normal betrachten, mĂŒssen Sie die Texturkoordinaten nicht stark verschieben, wĂ€hrend bei einem Blickwinkel die Verschiebung zum Maximum tendiert (stellen Sie sich in beiden FĂ€llen mental die Blickrichtung vor). Wenn Sie die Anzahl der Proben in AbhĂ€ngigkeit von der Blickrichtung parametrisieren, können Sie eine Menge sparen, wenn keine zusĂ€tzlichen Proben benötigt werden:
const float minLayers = 8.0; const float maxLayers = 32.0; float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0.0, 0.0, 1.0), viewDir)));
Das Ergebnis des Skalarprodukts der VektoransichtDir und der positiven Halbachse Z wird verwendet, um die Anzahl der Schichten im Intervall [
minSamples ,
maxSamples ] zu bestimmen, d.
H. Die Blickrichtung bestimmt die erforderliche Anzahl von Iterationen des Effekts (im Tangentenraum ist die positive Halbachse Z senkrecht zur OberflĂ€che gerichtet). Wenn wir parallel zur OberflĂ€che schauen wĂŒrden, wĂŒrde der Effekt alle 32 Ebenen verwenden.
GeÀnderter Quellcode ist
hier . Ich schlage auch vor, die Textur eines Holzspielzeugs herunterzuladen:
diffuse ,
normale Karte, Tiefenkarte .
Nicht ohne Ansatz und Nachteile. Da die Anzahl der Samples alle gleich endlich ist, ist das Auftreten von Aliasing-Effekten unvermeidlich, wodurch die ĂbergĂ€nge zwischen den Schichten auffĂ€llig werden:
Sie können den Schweregrad des Artefakts verringern, indem Sie die Anzahl der verwendeten Samples erhöhen, aber es verbraucht ziemlich schnell die gesamte verfĂŒgbare Videoprozessorleistung. Es gibt mehrere ErgĂ€nzungen zu der Methode, die als Ergebnis nicht den ersten Punkt zurĂŒckgeben, der unter dem imaginĂ€ren Relief der OberflĂ€che erschien, sondern den interpolierten Wert der beiden nĂ€chstgelegenen Schichten, wodurch wir die Position des Punktes weiter klĂ€ren können
colorblueB .
Von diesen Methoden werden am hÀufigsten zwei verwendet:
Relief Parallax Mapping und
Parallax Occlusion Mapping , wobei Relief PM die zuverlÀssigsten Ergebnisse liefert, aber auch etwas leistungsintensiver ist als Parallax Occlusion Mapping. Da Parallax Occlusion Mapping in der QualitÀt von Relief PM immer noch sehr Àhnlich ist und gleichzeitig schneller arbeitet, bevorzugen sie es, es am hÀufigsten zu verwenden. Als nÀchstes wird die Implementierung von Parallax Occlusion Mapping betrachtet.
Parallax Occlusion Mapping
Die Parallax Occlusion Mapping-Methode arbeitet alle nach den gleichen Grundprinzipien wie Steep PM. Statt jedoch die Texturkoordinaten der ersten Ebene zu verwenden, bei der ein Schnittpunkt mit einem imaginĂ€ren Relief gefunden wurde, verwendet die Methode eine lineare Interpolation zwischen zwei Ebenen: der Ebene nach und vor dem Schnittpunkt. Der Gewichtungskoeffizient fĂŒr die lineare Interpolation basiert auf dem VerhĂ€ltnis der aktuellen Relieftiefe zu den Tiefen beider betrachteten Schichten. Schauen Sie sich das Diagramm an, um besser zu verstehen, wie alles funktioniert:
Wie Sie sehen können, ist alles dem steilen PM sehr Ă€hnlich. Es wird nur ein zusĂ€tzlicher Schritt zum Interpolieren der Texturkoordinaten der beiden Tiefenschichten neben dem Schnittpunkt hinzugefĂŒgt. NatĂŒrlich ist eine solche Methode nur eine AnnĂ€herung, aber viel genauer als eine steile PM.
Der Parallax Occlusion Mapping-Code ist zusÀtzlich zum Steep PM-Code und nicht zu kompliziert:
[...]
In dem Moment, in dem die nach dem Schnittpunkt liegende Schicht mit dem imaginĂ€ren Relief gefunden wird, bestimmen wir auch die Texturkoordinaten der vor dem Schnittpunkt liegenden Schicht. Als nĂ€chstes finden wir die Verschiebungen der imaginĂ€ren Relieftiefe relativ zu den Tiefen der beiden betrachteten Schichten und verwenden ihr VerhĂ€ltnis als Gewichtskoeffizienten fĂŒr die weitere lineare Interpolation der Texturkoordinaten, die den beiden betrachteten Schichten entsprechen. Das Ergebnis der Interpolation wird von der Funktion zur zukĂŒnftigen Verwendung zurĂŒckgegeben.
Parallax Occlusion Mapping liefert ĂŒberraschend visuell zuverlĂ€ssige Ergebnisse, wenn auch mit kleinen Fehlern und Aliasing-Artefakten. FĂŒr einen Kompromiss in Geschwindigkeit und QualitĂ€t sind sie jedoch unbedeutend und erscheinen nur bei genauer Beobachtung der OberflĂ€che in der NĂ€he der Kamera oder bei sehr scharfen Betrachtungswinkeln.
Ein Beispielcode ist
hier .
Parallax Mapping ist wirklich eine hervorragende Technik, mit der Sie die visuellen Details Ihrer Szene dramatisch verbessern können, hat aber natĂŒrlich auch Nachteile in Form von Artefakten, die bei der Implementierung der Technik im Projekt berĂŒcksichtigt werden sollten. Die Parallaxenzuordnung wird gröĂtenteils auf ebenen FlĂ€chen wie WĂ€nden oder Böden verwendet - wo es nicht so einfach ist, den Umriss des gesamten Objekts zu bestimmen, und der Blickwinkel der OberflĂ€che oft nahe an der Senkrechten liegt. In diesem Fall sind Parallax Mapping-Fehler vor dem Hintergrund erhöhter OberflĂ€chendetails nahezu unsichtbar.
Boni vom Ăbersetzer:
Relief Parallax Mapping
Da der Autor der VollstÀndigkeit halber zwei Methoden zur KlÀrung des Ergebnisses von Steep PM erwÀhnt hat, werde ich den zweiten der AnsÀtze beschreiben.
Wie bei der Parallax Occlusion Mapping wird hier das Ergebnis der steilen PM-AusfĂŒhrung verwendet, d. H. Wir kennen die Tiefen zweier Schichten, zwischen denen der eigentliche Schnittpunkt des Vektors liegt
colororange barV mit Relief sowie die entsprechenden Texturkoordinaten
T2 und
T3 . Die Verfeinerung der SchÀtzung des Schnittpunkts bei dieser Methode beruht auf der Verwendung der binÀren Suche.
Schritte des Verfeinerungsalgorithmus:
- FĂŒhren Sie eine steile PM-Berechnung durch und erhalten Sie Texturkoordinaten T2 und T3 - In diesem Intervall liegt der Schnittpunkt des Vektors c o l o r g r e e n b ein R V mit OberflĂ€chentopographie. Die wahre Kreuzung ist mit einem roten Kreuz markiert.
- Teilen Sie den Versatz der Texturkoordinaten und die Höhe der Tiefenebene in zwei aktuelle Werte.
- Verschieben Sie die Texturkoordinaten vom Punkt T 3 in der dem Vektor entgegengesetzten Richtung c o l o r g r e e n b ein R V um den Betrag der Verschiebung. Reduzieren Sie die Ebenentiefe um den aktuellen Wert fĂŒr die EbenengröĂe.
- Direkt binÀre Suche. Die angegebene Anzahl von Iterationen wird wiederholt:
- WĂ€hlen Sie aus der Tiefenkarte. Teilen Sie den aktuellen Texturversatz und die TiefenebenengröĂe in zwei aktuelle Werte.
- Wenn die StichprobengröĂe gröĂer als die aktuelle Ebenentiefe ist, erhöhen Sie die Ebenentiefe um die aktuelle EbenengröĂe und Ă€ndern Sie die Texturkoordinaten entlang des Vektors c o l o r g r e e n b ein R V auf den aktuellen Offset.
- Wenn die StichprobengröĂe kleiner als die aktuelle Ebenentiefe ist, reduzieren Sie die Ebenentiefe um die aktuelle EbenengröĂe und Ă€ndern Sie die Texturkoordinaten entlang des inversen Vektors c o l o r g r e e n b ein R V auf den aktuellen Offset.
- Die zuletzt erhaltenen Texturkoordinaten sind die Ergebnisse von Relief PM.

Das Bild zeigt das nach dem Finden der Punkte
T 2 und
T 3 Wir halbieren die GröĂe der Ebene und die GröĂe des Versatzes der Texturkoordinaten, wodurch wir den ersten Iterationspunkt der binĂ€ren Suche erhalten (1). Da sich herausstellte, dass die StichprobengröĂe gröĂer als die aktuelle Tiefe der Ebene ist, halbieren wir die Parameter erneut und bewegen uns weiter
c o l o r g r e e n b ein R V Punkt (2) mit Texturkoordinaten erhalten
T p Dies ist das Ergebnis von Steep PM fĂŒr zwei Iterationen der binĂ€ren Suche.
Shader Code:
Selbstbeschattung
Auch eine kleine ErgĂ€nzung zum HinzufĂŒgen von Schattierungen von einer ausgewĂ€hlten Lichtquelle zum Berechnungsalgorithmus. Ich habe mich fĂŒr das HinzufĂŒgen entschieden, da die Berechnungsmethode technisch mit den oben genannten identisch ist, der Effekt jedoch immer noch interessant ist und Details hinzufĂŒgt.TatsĂ€chlich wird dieselbe steile PM angewendet, aber die Suche geht nicht tief in die simulierte OberflĂ€che entlang der Sichtlinie, sondern von der OberflĂ€che entlang des Vektors zur LichtquelleË L. .
Dieser Vektor wird auch in den Tangentenraum ĂŒbertragen und zur Bestimmung des Verschiebungsbetrags der Texturkoordinaten verwendet. Am Ausgang des Verfahrens wird im Intervall [0, 1] ein Materialbeleuchtungskoeffizient erhalten, mit dem die diffusen und Spiegelkomponenten in Beleuchtungsberechnungen moduliert werden.Um eine Schattierung mit scharfen Kanten zu definieren, gehen Sie einfach entlang des VektorsË L bis ein Punkt unter der OberflĂ€che liegt. Sobald ein solcher Punkt gefunden wird, nehmen wir den Beleuchtungskoeffizienten 0. Wenn wir die Tiefe Null erreichen, ohne einen unter der OberflĂ€che liegenden Punkt zu treffen, nehmen wir den Beleuchtungskoeffizienten gleich 1.Um die Schattierung mit weichen Kanten zu bestimmen, mĂŒssen mehrere auf dem Vektor liegende Punkte ĂŒberprĂŒft werdenË L und befindet sich unter der OberflĂ€che. Der Schattierungsfaktor wird gleich der Differenz zwischen der Tiefe der aktuellen Ebene und der Tiefe aus der Tiefenkarte genommen. BerĂŒcksichtigt wird auch die Entfernung des nĂ€chsten Punktes aus dem fraglichen Fragment in Form eines Gewichtskoeffizienten von (1,0 - stepIndex / numberOfSteps). Bei jedem Schritt wird ein Teilbeleuchtungskoeffizient bestimmt als:P S F i = ( l a y e r H e i g h t i - h e i g h t F r o m t e x t u r e i ) * ( 1,0 - in u m S t e p s )
Das Endergebnis ist der maximale Lichtfaktor aller partiellen:S F = m a x ( P S F i )
Das Schema der Methode:Der Fortschritt der Methode fĂŒr drei Iterationen in diesem Beispiel:- Wir initialisieren den Gesamtlichtfaktor auf Null.
- Machen Sie einen Schritt entlang des Vektors Ë L , auf den Punkt kommenH a . Die Punkttiefe ist deutlich geringer als die Auswahl aus der Karte. H ( T L 1 ) - es befindet sich unter der OberflĂ€che. Hier haben wir die erste PrĂŒfung durchgefĂŒhrt und unter BerĂŒcksichtigung der Gesamtzahl der PrĂŒfungen den ersten Teillichtfaktor gefunden und gespeichert: (1,0 - 1,0 / 3,0).
- Machen Sie einen Schritt entlang des Vektors Ë L , auf den Punkt kommenH b . Die Punkttiefe ist deutlich geringer als die Auswahl aus der Karte. H ( T L 2 ) - es befindet sich unter der OberflĂ€che. Die zweite PrĂŒfung und der zweite Teilkoeffizient: (1,0 - 2,0 / 3,0).
- Wir machen noch einen Schritt entlang des Vektors und erreichen die minimale Tiefe von 0. Stoppen Sie die Bewegung.
- Definition des Ergebnisses: Wenn keine Punkte unter der OberflĂ€che gefunden wurden, geben wir einen Koeffizienten von 1 zurĂŒck (keine Schattierung). Andernfalls wird der resultierende Koeffizient zum Maximum der berechneten Teilkoeffizienten. FĂŒr die Verwendung in Beleuchtungsberechnungen subtrahieren wir diesen Wert von der Einheit.
Shader-Code-Beispiel:
Der resultierende Koeffizient wird verwendet, um das Ergebnis des in den Beispielen verwendeten Blinn-Fong-Beleuchtungsmodells zu modulieren: [...]
Vergleich aller Methoden in einer Collage, 3 MB Volumen.Auch ein Videovergleich:ZusÀtzliche Materialien
PS : Wir haben ein Telegramm Conf fĂŒr die Koordination der Ăberweisungen. Wenn Sie ernsthaft bei der Ăbersetzung helfen möchten, sind Sie herzlich willkommen!