- Triển khai trình render phần mềm từ đầu, không dùng thư viện đồ họa bên ngoài, để hiểu nguyên lý hoạt động bên trong của OpenGL, Vulkan, Metal và DirectX
- Chuyển đổi mô hình 3D thành hình ảnh từ mesh tam giác và texture; không đề cập đến việc triển khai GUI hay ứng dụng GPU
- Mã hoàn chỉnh khoảng 500 dòng, và sinh viên thường mất 10–20 giờ để bắt đầu tạo được một trình render hoạt động
- Chỉ được cung cấp lớp xử lý TGA hỗ trợ RGB, RGBA và thang xám, cùng chức năng đặt một pixel đơn lẻ; việc vẽ đoạn thẳng và tam giác phải tự triển khai
- Cần tự viết thay vì sao chép mã hoàn chỉnh để hiểu các khái niệm render và nắm được cách hoạt động bên trong của thư viện 3D
Quá trình tự xây dựng pipeline render
- Học nguyên lý hoạt động của pipeline render bằng cách mô phỏng lỏng lẻo cấu trúc của các thư viện đồ họa 3D hiện đại
- Tái hiện cơ chế bên trong bằng trình render phần mềm thay vì cách viết ứng dụng GPU
- Đầu vào là mô hình 3D gồm mesh tam giác và texture, đầu ra là hình ảnh đã render
- Chương trình tạo tệp hình ảnh mà không có giao diện đồ họa
- Sử dụng định dạng hình ảnh đơn giản TGA để giảm phụ thuộc bên ngoài
- Chức năng ban đầu được cung cấp chỉ gồm tải/lưu hình ảnh và đặt màu cho một pixel
- Không có hàm tích hợp để vẽ đoạn thẳng hay tam giác, nên tất cả phải tự viết
- Ví dụ khởi đầu tạo framebuffer RGB
64x64, đặt pixel tại ba tọa độ thành màu trắng rồi lưu thành framebuffer.tga
- Giá trị màu được chỉ định theo thứ tự BGRA
Build và chạy mã
git clone https://github.com/ssloy/tinyrenderer.git &&
cd tinyrenderer &&
cmake -Bbuild &&
cmake --build build -j &&
build/tinyrenderer obj/diablo3_pose/diablo3_pose.obj obj/floor.obj
- Kết quả chạy được lưu vào
framebuffer.tga
- Dù mã hoàn chỉnh chỉ khoảng 500 dòng, quá trình tự triển khai là thiết yếu để hiểu khái niệm, nên không khuyến nghị dùng nguyên xi mã được cung cấp
1 bình luận
Ý kiến trên Hacker News
https://github.com/kshitijl/tinyrenderer-rs
Kho lưu trữ có rất nhiều ảnh chụp màn hình về quá trình phát triển và những lỗi hiển thị buồn cười. Tôi học được rất nhiều không chỉ về nguyên lý dựng hình mà còn về việc CPU hiện đại nhanh đến mức nào, và rằng ngay cả trình dựng hình CPU đơn luồng cũng có thể chạy game 3D tương tác với hiệu ứng đặc biệt khá hào nhoáng
Đây là trước thời LLM nên mất ít nhất hai tháng, và phần lớn thời gian là để hiểu toán đồ họa máy tính và lần theo các lỗi segmentation fault của C
Bộ ghi chú bài giảng trên GitHub này phù hợp hơn để ôn lại các khái niệm. Tôi không thích phong cách mã trong kho này, và bộ rasterizer kiểu cũ cũng quá đơn giản và kém hiệu quả, nhưng dù sao tôi vẫn thấy nó dễ đọc hơn sách của Foley
Qua các lần tái bản, ngôn ngữ sử dụng cũng phát triển từ Pascal sang C, rồi C và C++, và bản mới nhất còn có thêm một chút C#. Một số khái niệm mới đã bị lược bỏ, nhưng tôi vẫn nghĩ vẫn còn rất nhiều nội dung có giá trị
Frustum clipping có thể xử lý bằng cách chọn điểm theo tile cục bộ, còn gộp primitive thì dễ hơn nếu xử lý hình chữ nhật clipping đã biến đổi ngược trong hệ tọa độ barycentric. Có thể kiểm soát sai số làm tròn bằng số thực độ chính xác kép hoặc số cố định, và điểm khó cốt lõi là tái tạo giá trị Z và 1/Z của đỉnh mới. Với rasterizer gộp thuộc tính trì hoãn thì phần còn lại sẽ tự nhiên đi xuyên suốt pipeline, và có thể xem ví dụ trong phần triển khai mã nguồn mở của OpenSWR.org
Rào cản tâm lý lớn nhất là sự xa lạ của không gian chiếu và tọa độ thuần nhất. Sáu mặt phẳng của clip space rất đơn giản:
x = ±w,y = ±w,z = ±w; chỉ cần duyệt từng cạnh của đa giác, xác định xem hai đầu mút nằm trong hay ngoài, rồi nội suy tuyến tính vị trí giao điểm với biên và các thuộc tính đỉnh. Áp dụng quá trình này lần lượt cho mọi mặt phẳng thì tam giác sẽ trở thành một đa giác lồi có tối đa 9 đỉnh và có thể dễ dàng chia tam giác lại. Nếu tính sẵn outcode thì có thể bỏ qua clipping cho các tam giác nằm hoàn toàn bên trong hoặc bên ngoàiBài báo: https://dl.acm.org/doi/10.1145/360767.360802
Nếu giữ dạng fixed pipeline thì ngay cả với các hàm vẽ khá đơn giản cũng có thể xử lý được số lượng tam giác đáng ngạc nhiên