Tôi có một bề mặt địa hình với một điểm bình thường cho mỗi điểm trên địa hình.
Tôi có một chi tiết thứ hai bản đồ bình thường được áp dụng cho địa hình.
Các quy tắc này là trong 3 không gian.
Giá trị Y của cả hai giá trị luôn là dương.
Các giá trị X, Z của cả hai quy tắc có thể dương / âm / không.
Vectơ bình thường thứ nhất (màu xanh) mà chúng ta đang xoay vectơ thứ 2 (màu cam) theo, có thể gần như nằm ngang.
Tôi ổn với một giải pháp gần đúng nếu nó làm cho nó dễ dàng hơn / nhanh hơn để tính toán.
Trong hình trên, bạn thấy bề mặt màu xanh bình thường (từ bản đồ bình thường thứ 1), bản đồ bình thường màu cam bình thường (từ bản đồ bình thường thứ 2) và kết quả màu xanh lá cây mong muốn bình thường.
Số lượng mà vectơ màu cam được xoay phải xấp xỉ (hoặc nếu có thể chính xác) bằng với góc mà vectơ bình thường màu xanh tạo thành với mặt phẳng XZ (trong đó Y lên, giống như hệ tọa độ DirectX).
Đây là một kịch bản thứ hai:
Trong hình trên, bề mặt màu xanh bình thường gần như nằm ngang, do đó bản đồ bình thường thứ 2 đang được áp dụng cho bề mặt gần như thẳng đứng, do đó, vectơ bản đồ màu cam bình thường được xoay thêm.
Việc xoay vòng đang được thực hiện trong một shader HLSL.
Làm cách nào để xoay quả cam thứ 1 bình thường dựa trên hướng của màu xanh thứ 2 bình thường?
Chỉnh sửa: Có lẽ tôi cần một tiếp tuyến và bitangent như bình thường?
Đây là cách tôi có được bình thường:
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);
}
Làm thế nào tôi có thể có được các vectơ tiếp tuyến và bitangent sau đó?
Có đủ để lấy sản phẩm chéo của bình thường với vectơ đơn vị trục Z để tìm vectơ tiếp tuyến không? (Vì bình thường. Y luôn dương, trong đó Y lên và Z đang chỉ vào màn hình của bạn).
Và sau đó lấy vectơ tiếp tuyến đó và vượt qua nó với bình thường để thu được bitangent?
Và sau đó lấy các bình thường, tiếp tuyến và bitangent với nhau để tạo thành một ma trận xoay để xoay vector bản đồ bình thường màu cam?
Ngay cả khi điều đó hoạt động, điều này có vẻ như rất nhiều tính toán cho một shader pixel. Điều này có hiệu quả không, và có cách nào hiệu quả hơn không?
Biên tập:
Hình ảnh này có thể giúp bạn hiểu những gì tôi đang cố gắng làm:
Nếu bạn biết ánh xạ bình thường là gì, thì điều này nên đơn giản, tôi nghĩ vậy.
Tôi đang cố gắng lấy bản đồ bình thường, chứa các quy tắc khác nhau và áp dụng chúng lên một bề mặt. Bề mặt có quy tắc riêng của nó. Bản đồ bình thường sẽ chứa nhiều quy tắc hơn bề mặt, do đó, một số quy tắc bản đồ bình thường được lấy mẫu trên một phần của bề mặt chỉ có một bình thường duy nhất.