Eu tenho uma superfície de terreno com um normal para cada ponto no terreno.
Eu tenho um segundo mapa normal de detalhes a ser aplicado ao terreno.
Essas normais estão em 3 espaços.
O valor Y de ambos os normais é sempre positivo.
Os valores X, Z de ambos os normais podem ser positivos / negativos / zero.
O primeiro vetor normal (azul) pelo qual estamos girando o segundo vetor (laranja) pode ser quase horizontal.
Eu estou bem com uma solução aproximada, se torna mais fácil / rápido calcular.
Na imagem acima, você vê a superfície azul normal (no 1º mapa normal), o mapa normal laranja (no segundo mapa normal) e o resultado desejado verde normal.
A quantidade em que o vetor laranja é rotacionado deve ser aproximadamente (ou se possível) exatamente igual ao ângulo que o vetor normal azul forma com o plano XZ (onde Y está ativo, como o sistema de coordenadas do DirectX).
Aqui está um segundo cenário:
Na imagem acima, a superfície azul normal é quase horizontal; portanto, o 2º mapa normal está sendo aplicado a uma superfície quase vertical, assim o vetor laranja normal do mapa é girado ainda mais.
A rotação está sendo implementada em um shader HLSL.
Como eu giro a 1ª normal de laranja com base na direção da 2ª normal de azul?
Edit: Talvez eu precise de uma tangente e bitangente, bem como o normal?
Aqui está como eu obtenho o normal:
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);
}
Como posso obter os vetores tangente e bitangente?
É suficiente pegar o produto cruzado do normal com o vetor unitário do eixo Z para encontrar o vetor tangente? (Como o normal.Y é sempre positivo, onde Y está ativo e Z está apontando na tela).
E então pegue esse vetor tangente e cruze-o com o normal para obter o bitangente?
E então pegue o normal, tangente e bitangente juntos para formar uma matriz de rotação para girar o vetor de mapa normal laranja?
Mesmo que isso funcione, parece muita computação para um pixel shader. Isso funciona e existe uma maneira mais eficiente?
Editar:
Esta imagem pode ajudá-lo a entender o que estou tentando fazer:
Se você sabe o que é o mapeamento normal, acho que isso deve ser direto.
Estou tentando pegar o mapa normal, que contém vários normais, e aplicá-los a uma superfície. A superfície tem seus próprios normais. O mapa normal conterá muito mais normais do que a superfície; portanto, vários normais normais do mapa são amostrados em uma única parte da superfície que possui apenas um único normal.