Ich habe eine Geländefläche mit einer Normalen für jeden Punkt im Gelände.
Ich habe eine zweite Detail-Normalkarte, die auf das Gelände angewendet werden soll.
Diese Normalen liegen im 3-Raum.
Der Y-Wert beider Normalen ist immer positiv.
Die X-, Z-Werte beider Normalen können positiv / negativ / null sein.
Der 1. Normalvektor (blau), um den wir den 2. Vektor (orange) drehen, kann fast horizontal sein.
Ich bin mit einer ungefähren Lösung einverstanden, wenn sie das Berechnen einfacher / schneller macht.
Im obigen Bild sehen Sie die blaue Oberflächennormale (von der 1. Normalkarte), die orange Normale Normalen (von der 2. Normalkarte) und die grüne gewünschte Ergebnisnormale.
Der Betrag, um den der orangefarbene Vektor gedreht wird, sollte ungefähr (oder wenn möglicherweise genau) dem Winkel entsprechen, den der blaue Normalenvektor mit der XZ-Ebene bildet (wobei Y oben ist, wie das DirectX-Koordinatensystem).
Hier ist ein zweites Szenario:
In dem obigen Bild ist die blaue Oberflächennormale fast horizontal, so dass die 2. Normalkarte auf eine fast vertikale Fläche angewendet wird, wodurch der orangefarbene Normalkartenvektor weiter gedreht wird.
Die Rotation wird in einem HLSL-Shader implementiert.
Wie drehe ich die 1. orange Normale basierend auf der Richtung der 2. blauen Normalen?
Edit: Vielleicht brauche ich eine Tangente und Bitangente sowie die normale?
So komme ich zum Normalen:
float4 ComputeNormals(VS_OUTPUT input) : COLOR
{
float2 uv = input.TexCoord;
// top left, left, bottom left, top, bottom, top right, right, bottom right
float tl = abs(tex2D(HeightSampler, uv + TexelSize * float2(-1, -1)).x);
float l = abs(tex2D(HeightSampler, uv + TexelSize * float2(-1, 0)).x);
float bl = abs(tex2D(HeightSampler, uv + TexelSize * float2(-1, 1)).x);
float t = abs(tex2D(HeightSampler, uv + TexelSize * float2( 0, -1)).x);
float b = abs(tex2D(HeightSampler, uv + TexelSize * float2( 0, 1)).x);
float tr = abs(tex2D(HeightSampler, uv + TexelSize * float2( 1, -1)).x);
float r = abs(tex2D(HeightSampler, uv + TexelSize * float2( 1, 0)).x);
float br = abs(tex2D(HeightSampler, uv + TexelSize * float2( 1, 1)).x);
// Compute dx using Sobel filter.
// -1 0 1
// -2 0 2
// -1 0 1
float dX = tr + 2*r + br - tl - 2*l - bl;
// Compute dy using Sobel filter.
// -1 -2 -1
// 0 0 0
// 1 2 1
float dY = bl + 2*b + br - tl - 2*t - tr;
// Compute cross-product and renormalize
float3 N = normalize(float3(-dX, NormalStrength, -dY));
// Map [-1.0 , 1.0] to [0.0 , 1.0];
return float4(N * 0.5f + 0.5f, 1.0f);
}
Wie könnte ich dann die Tangenten- und Bitangensvektoren erhalten?
Reicht es aus, das Kreuzprodukt der Normalen mit dem Einheitsvektor der Z-Achse zu nehmen, um den Tangentenvektor zu finden? (Da das normale.Y immer positiv ist, wo Y oben ist und Z in Ihren Bildschirm zeigt).
Und dann nimm diesen Tangentenvektor und kreuze ihn mit der Normalen, um den Bitangens zu erhalten?
Und dann nehmen Sie die Normalen, Tangenten und Bitangens zusammen, um eine Rotationsmatrix zu bilden, um den orangefarbenen normalen Kartenvektor zu drehen?
Selbst wenn das funktioniert, scheint dies eine Menge Berechnung für einen Pixel-Shader zu sein. Funktioniert das und gibt es einen effizienteren Weg?
Bearbeiten:
Dieses Bild kann Ihnen helfen zu verstehen, was ich versuche zu tun:
Wenn Sie wissen, was normales Mapping ist, sollte dies meiner Meinung nach unkompliziert sein.
Ich versuche, die normale Karte, die verschiedene Normalen enthält, auf eine Oberfläche anzuwenden. Die Oberfläche hat ihre eigenen Normalen. Die normale Karte enthält viel mehr Normalen als die Oberfläche, sodass mehrere normale Kartennormalen über einen einzelnen Teil der Oberfläche abgetastet werden, der nur eine einzige Norm enthält.
quelle
Antworten:
Ich glaube, ich verstehe Ihre Frage, obwohl der Titel und die beiden ersten Bilder verwirrend sind.
Das Problem ist, dass eine Normalkarte auf einer xz-Ebene (dem orangefarbenen Vektor) abgebildet werden muss. Nun ist die durch die blaue Normale beschriebene tatsächliche Ebene nicht unbedingt in der xz-Ebene, so dass man eine Drehung von der xz-Ebene zur tatsächlichen Ebene finden muss, um den orangefarbenen Vektor zu drehen, um ihn auf der tatsächlichen Ebene abzubilden.
Wie können wir das jetzt tun? Bacial müssen wir die Drehung finden, die die xz-Ebene zu der durch die blaue Normale beschriebenen Ebene dreht.
Finden Sie die Rotationsachse, indem Sie das Kreuzprodukt der blauen Normalen und der Normalen aus der xz-Ebene {0, 1, 0} nehmen. Der orangefarbene Vektor muss um diese Achse gedreht werden.
Finden Sie den Drehwinkel, indem Sie Arccosin des Punktprodukts beider Normalen nehmen
Jetzt eine Rotationsmatrix erstellen aus diesen Werten und die orangefarbenen Normal mit dieser Matrix - Transformation.
quelle
Ich glaube, Sie haben Ihr Problem überlegt.
Um zur normalen Standardabbildung zurückzukehren, haben Sie normalerweise 3 Vektoren: die Oberflächennormale, einen Tangentenvektor senkrecht zu diesem und einen Kotangens senkrecht zu beiden. Zusammen bilden diese den Tangentenraum, in dem die normale Karte eine Richtung beschreibt. Bei diesem Setup müssen Sie nur jede gelesene Komponente der normalen Karte mit ihrer jeweiligen Tangentenraumachse multiplizieren und die Ergebnisse summieren.
Sie haben also ein Gelände und eine normale Karte, die Sie darauf anwenden möchten. Sie haben bereits herausgefunden, wie Sie die Delta-Höhe nehmen und eine Oberflächennormale erzeugen können. Sie suchen jetzt nach Tangente und Kotangens.
Was ist also eine Tangente? Aus der obigen Beschreibung geht hervor, dass es sich tatsächlich um die 3D-Richtung handelt, die von einer der UV-Achsen in Ihrer Texturabbildung beschrieben wird. Dafür wird es doch benutzt, oder? Wie finden Sie diese Richtung? Nun, angesichts eines beliebigen Netzes ist es ein wenig schwierig; Bei einem regelmäßigen Gittergelände ist es jedoch selbstverständlich: Wenn Sie ein reguläres Gitter mit regelmäßigen UV-Strahlen haben, sind die Tangenten- und Kotangensrichtungen nur die beiden achsenausgerichteten Kanten, die Ihren Scheitelpunkt verlassen.
Sie wissen also, wie hoch die Punkte um Sie herum sind. Sie können eingeben, wie weit diese Punkte im Flugzeug entfernt sind. Subtrahieren Sie diese von dem Punkt, an dem Sie sich befinden, normalisieren Sie und los geht's: Sofortiger Tangentenraum.
quelle
Wenn Sie auch die Tangente haben, können Sie diese Funktion verwenden, um die gestoßene Normalen zu erzeugen, nach denen Sie suchen. Andernfalls können Sie in Zukunft plagiieren!
quelle
Sie können die LERP-Funktion verwenden, die linear zwischen den beiden Vektoren interpoliert. Wir geben Ihnen eine schöne "gemittelte" Normalität.
http://msdn.microsoft.com/en-us/library/bb509618(VS.85).aspx
(Natürlich dreht sich das nicht wirklich, aber angesichts des orangefarbenen und blauen Vektors erhalten Sie den grünen Vektor.)
quelle