Phối cảnh ánh xạ kết cấu chính xác


7

Vì vậy, tôi đang cố gắng ánh xạ chính xác họa tiết của mình trong trình kết xuất phần mềm bằng tọa độ u, v nhưng dường như tôi không thể làm cho nó hoạt động được. Tôi có bản đồ kết cấu affine làm việc. Đây là những gì tôi có thể sản xuất bằng cách sử dụng nó:

nhập mô tả hình ảnh ở đây

Bạn có thể thấy từ "độ nghiêng" trong kết cấu không hoàn toàn đúng. Nếu tôi thêm nhiều hình tam giác vào lưới thì nó trở nên chính xác hơn. Theo hiểu biết của tôi đây không phải là kết cấu chính xác. Nhưng quan điểm phân chia điều này là gây nhầm lẫn cho tôi. Tôi đọc rằng tôi cần chia tọa độ u, v cho thành phần w (chia phối cảnh). Tôi đoán rằng đây là thành phần w từ đỉnh sau khi nhân với ma trận chiếu. Nhưng tôi không thể làm việc đó quá. Vì vậy, tôi nhìn thêm một chút vào vấn đề. Đầu tiên, đây là những gì đang xảy ra với một đỉnh của tam giác của tôi.

float4 pt1 = worldViewProj * mesh->vertices[mesh->indices[i]];
float2 uv1 = mesh->texCoords[mesh->indices[i]];
triangle.p1 = float3((pt1.x / pt1.w + 0.5f) * screen->GetScreenWidth(), (pt1.y / pt1.w + 0.5f) * screen->GetScreenHeight(), pt1.w);

Tôi nhân nó với wVP và sau đó phân chia phối cảnh của tôi với x và y. + 0,5f là căn giữa nó trong không gian đồng nhất và sau đó nhân với kích thước màn hình để có được nó trong không gian màn hình. Sau đó tôi nhồi thành phần w của đỉnh làm giá trị z để nó sẽ được gửi đến hàm vẽ tam giác và có thể được sử dụng cho những thứ như bộ đệm độ sâu.

Theo hiểu biết của tôi, giá trị z từ đỉnh được đặt vào w sau khi nhân với ma trận chiếu. Điều này có ý nghĩa vì m32 = 1 trong ma trận chiếu của tôi. Vậy sau khi nhân với ma trận chiếu w = z. Trước tiên tôi đã thử chia tọa độ kết cấu cho mỗi đỉnh cho w. Thích như vậy:

 float2 uv1 = mesh->texCoords[mesh->indices[i]] / w;

Sau đó, trong hàm vẽ tam giác, tôi đã sử dụng tọa độ trung tâm bary để nội suy trên các tọa độ uv này. Điều này đã không làm việc. Vì w = z. Khi kết cấu ở xa máy ảnh (tức là z là một giá trị lớn. Với các bản dịch thế giới của tôi được áp dụng z = ~ 700) thì tọa độ kết cấu co lại rất nhiều và trong mỗi kết xuất, tôi chỉ nhận được giá trị (0, 0) của kết cấu .

Nhưng tôi cũng đã thử điều này thay vào đó trong chức năng vẽ tam giác của mình:

float2 texCoord = (texCoord1 * u + texCoord2 * v + texCoord3 * w) / z;

(Ở đây u, v và w là tọa độ trung tâm bary. Mỗi texCoord là kết cấu Tọa độ tại đỉnh đó) Sự khác biệt ở đây là giá trị z nội suy đang được chia ở mỗi pixel thay vì được chia ở các đỉnh. Dù bằng cách nào tôi dường như không thể làm cho nó quá công việc. Một lần nữa, giá trị z quá lớn và cuối cùng tôi nhận được (0, 0).

Vì vậy, tôi đang điều tra những gì tôi cần để chia u và v cho. Rõ ràng là tôi đang làm gì đó sai. Có thực sự là thành phần w của đỉnh sau khi nhân với ma trận chiếu? Là giá trị w của tôi sai? Ma trận chiếu có thể gây ra điều này? Bây giờ tôi đã loay hoay một lúc rồi ... x / w và y / w là [-1, 1] (đồng nhất) nhưng z không phải là [-1, 1]. Nó được cho là? Quan điểm của tôi phân chia cho x và y rõ ràng hoạt động.

Đây là cách tôi xây dựng ma trận chiếu của mình trong trường hợp nó sai?:

float tanHalfFov = tanf(fov * 0.5f * 3.14f / 180.0f);
float s = 1.0f / (tanHalfFov * aspectRatio);
float zRange = farZ - nearZ;

// Set the projection matrix
proj.m00 = s;    proj.m01 = 0.0f;            proj.m02 = 0.0f;          proj.m03 = 0.0f;

proj.m10 = 0.0f; proj.m11 = aspectRatio * s; proj.m12 = 0.0f;          proj.m13 = 0.0f;

proj.m20 = 0.0f; proj.m21 = 0.0f;            proj.m22 = farZ / zRange; proj.m23 = farZ * nearZ / zRange;

proj.m30 = 0.0f; proj.m31 = 0.0f;            proj.m32 = 1.0f;          proj.m33 = 0.0f;

2
Ma trận chiếu biến đổi các điểm thành không gian clip , đó là một khối 2x2x2 có tâm ở gốc, không phải là thứ bạn đang gọi là "không gian màn hình". Các tọa độ đồng nhất có nghĩa là bạn có wthêm tọa độ không gian (x, y và có thể z). Nó không có gì để làm với bình thường hóa. Bạn không bao giờ chia cho Z - luôn luôn W. Điểm của W là bạn có thể phân chia phối cảnh và giữ độ sâu (một lần nữa, trong không gian clip) và cho phép bạn thêm bản dịch vào ma trận của mình thay vì có một bước riêng biệt. Bạn đang trộn lẫn rất nhiều khái niệm khác nhau.
3Dave

Câu trả lời:


6

Bạn đang đi đúng hướng nhưng điều bạn cần làm là tính toán u / w và v / w, và 1 / w cho mỗi đỉnh, mà bạn nội suy tuyến tính trong không gian màn hình trong trình rasterizer của bạn. Sau đó, với mỗi pixel, bạn chia tọa độ u / w và v / w nội suy với 1 / w nội suy để có được tọa độ uv chính xác phối cảnh cho pixel.

Điều tương tự cũng áp dụng cho tất cả các thuộc tính đỉnh, ví dụ: nếu bạn cần lấy màu chính xác hoặc vị trí của các đỉnh trên mỗi pixel, thì bạn nội suy c / w và p / w và chia các giá trị đó cho 1 / w cho mỗi pixel. Ngay cả khi bạn không triển khai trình rasterizer phần mềm, điều này có thể khá hữu ích, ví dụ như trong việc thực hiện phản xạ không gian màn hình. Tôi đã thấy những người thực hiện tia sáng diễu hành cho SSR trong không gian thế giới vì họ không biết cách nội suy đúng vị trí trong không gian màn hình.

Điều mà các trình raster phần mềm cũ thường làm là chỉ thực hiện phép chia 1 / (1 / w) này cho mỗi pixel X và nội suy tuyến tính các giá trị ở giữa vì phép chia này hoạt động tương đối tốn kém để thực hiện mọi pixel.


Là 1 / (1 / w) một lỗi đánh máy hoặc một cái gì đó tôi đã hiểu lầm?
trichoplax

2
Không phải là một lỗi đánh máy. Bạn nội suy 1 / w tuyến tính trên màn hình và tính 1 / (1 / w) cho mỗi pixel. Sau đó nhân u / w và v / w nội suy tuyến tính với giá trị 1 / (1 / w) trên mỗi pixel. Chỉ là một tối ưu hóa tầm thường của việc biến div thành muls để tránh nhiều phân chia trên mỗi pixel.
JarkkoL
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.