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.