Tôi phải viết phần mềm rasterizer 3d của riêng mình và cho đến nay tôi có thể chiếu mô hình 3d của mình làm bằng hình tam giác vào không gian 2d:
Tôi xoay, dịch và chiếu các điểm của mình để có được đại diện không gian 2d cho mỗi tam giác. Sau đó, tôi lấy 3 điểm tam giác và tôi thực hiện thuật toán quét (sử dụng phép nội suy tuyến tính) để tìm tất cả các điểm [x] [y] dọc theo các cạnh (trái và phải) của các tam giác, để tôi có thể quét tam giác theo chiều ngang, theo từng hàng và điền nó với pixel.
Những công việc này. Ngoại trừ tôi cũng phải thực hiện đệm z. Điều này có nghĩa là khi biết tọa độ z được xoay và dịch của 3 đỉnh của tam giác, tôi phải nội suy tọa độ z cho tất cả các điểm khác mà tôi tìm thấy bằng thuật toán scanline của mình.
Khái niệm này có vẻ đủ rõ ràng, trước tiên tôi tìm thấy Za và Zb với các tính toán sau:
var Z_Slope = (bottom_point_z - top_point_z) / (bottom_point_y - top_point_y);
var Za = top_point_z + ((current_point_y - top_point_y) * Z_Slope);
Sau đó, với mỗi Zp, tôi thực hiện phép nội suy tương tự theo chiều ngang:
var Z_Slope = (right_z - left_z) / (right_x - left_x);
var Zp = left_z + ((current_point_x - left_x) * Z_Slope);
Và nếu z hiện tại gần với người xem hơn z trước đó ở chỉ số đó thì hãy ghi màu vào bộ đệm màu VÀ ghi z mới vào bộ đệm z. (hệ tọa độ của tôi là x: left -> right; y: top -> bottom; z: khuôn mặt của bạn -> màn hình máy tính;)
Vấn đề là, nó đi haywire. Dự án ở đây và nếu bạn chọn nút radio "Bộ đệm Z", bạn sẽ thấy kết quả ... ( lưu ý rằng tôi sử dụng thuật toán của họa sĩ (-only- để vẽ khung dây) trong chế độ "Bộ đệm Z" cho mục đích gỡ lỗi )
PS: Tôi đã đọc ở đây rằng bạn phải biến z thành đối ứng của chúng (nghĩa là z = 1/z
) trước khi bạn nội suy. Tôi đã thử điều đó, và dường như không có thay đổi. Tôi đang thiếu gì? (bất cứ ai cũng có thể làm rõ, chính xác nơi bạn phải biến z thành 1 / z và nơi (nếu) để biến nó trở lại?)
[EDIT] Đây là một số dữ liệu về giá trị z tối đa và tối thiểu tôi nhận được:
max z: 1; min z: -1; //<-- obvious, original z of the vertices of the triangles
max z: 7.197753398761272; min z: 3.791703256899924; //<-- z of the points that were drawn to screen (you know, after rotation, translation), by the scanline with zbuffer, gotten with interpolation but not 1/z.
max z: 0.2649908532179404; min z: 0.13849507306889008;//<-- same as above except I interpolated 1/z instead of z.
//yes, I am aware that changing z to 1/z means flipping the comparison in the zBuffer check. otherwise nothing gets drawn.
Trước khi tôi đi vào việc sửa lỗi, ai đó có thể xác nhận rằng khái niệm của tôi cho đến nay là chính xác không?
[EDIT2]
Tôi đã giải quyết được bộ đệm z. Hóa ra, thứ tự vẽ không bị rối tung cả. Các tọa độ z đã được tính toán chính xác.
Vấn đề là, trong nỗ lực tăng tốc độ khung hình của tôi, tôi đã vẽ các hộp 4px / 4px, mỗi pixel thứ 4, thay vì các pixel thực trên màn hình. Vì vậy, tôi đã vẽ 16px cho mỗi pixel, nhưng chỉ kiểm tra bộ đệm z cho một trong số chúng. Tôi là một boob như vậy.
TL / DR: Câu hỏi vẫn đứng: Làm thế nào / tại sao / khi nào bạn phải sử dụng đối ứng của Z (như trong 1 / z) thay vì Z? Bởi vì ngay bây giờ, mọi thứ đều hoạt động. (không có sự khác biệt đáng chú ý).