2 điểm bởi GN⁺ 2 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • 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
  • Vài tháng trước tôi đã tự triển khai một software renderer bằng Rust mà không dùng LLM, rồi còn thêm một game đơn giản, shader kiểu pixel hóa và cả hiệu ứng quang sai màu ở rìa ánh đèn pin
    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
    • Tôi thắc mắc vì sao là software renderer mà vẫn phụ thuộc vào wgpu
    • Tôi thắc mắc khi viết logic game bằng Rust thì có cần thêm cả ECS hay không
  • Tài liệu này cùng với Mathematics for Computer Graphics của John Vince là những thứ thiết yếu để tôi tạo ra software renderer của mình
    Đâ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
    • Tôi tò mò không biết bạn đã làm mỗi ngày mấy tiếng trong suốt vài tháng đó
  • Tôi thắc mắc liệu cuốn sách của Foley và Van Dam có còn là tài liệu tham khảo tiêu biểu trong lĩnh vực này không. Nó đã được tái bản năm 2013, nhưng tôi quen với bản năm 1982 thiên về 2D hơn, và thời đó nó gần như là cuốn sách kinh điển của đồ họa máy tính
    • Đã lâu rồi tôi không mở lại nó, và với tôi nó gần giống một bách khoa toàn thư khá độc đáo có giá trị lịch sử hơn
      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
    • Tôi cũng học bằng bản 2 và cũng có bản mới nhất năm 2013, thấy nhìn chung là ổn
      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ị
  • Tôi ước gì có ít nhất một tutorial về software renderer xử lý triangle clipping cho ra hồn. Với một renderer thực dụng thì ngay cả ở cảnh cơ bản cũng nhất định phải xử lý khi hình học cắt vào view frustum, nhưng cá nhân tôi thấy đây là phần khó nhất
    • Chủ đề này được nói trọn một chương: https://gabrielgambetta.com/computer-graphics-from-scratch/11-clipping.html
    • Chỉ khi việc nội suy thuộc tính của các tam giác rất lớn là quan trọng thì mới cần triangle clipping, và có hai cách là loại bỏ nhanh hoặc gộp primitive
      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
    • Tôi cũng luôn bị mắc lại ở bước “phải triển khai clipping”, nhưng rốt cuộc vẫn viết được mã chạy ổn mà không quá khó, rồi sau này mới biết rằng mình đã tự tái khám phá thuật toán Sutherland–Hodgman một cách độc lập
      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ài
      Bài báo: https://dl.acm.org/doi/10.1145/360767.360802
  • Trong môi trường hiện đại thì thật ra không còn thứ gọi là C++ thuần túy. Bạn không thể như máy tính thập niên 1980 mà ghi trực tiếp vào thanh ghi và VRAM để xuất hình, cuối cùng vẫn phải phụ thuộc vào vô số mã nằm trên các lớp API, driver và firmware dày đặc
  • Tôi đang thử lại software rendering vì hoài niệm thập niên 1990, kết hợp bank CLUT kiểu 2D với kỹ thuật tam giác phân loại theo dải hiện đại và tọa độ barycentric
    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
  • Tôi đã phát hiện một lỗi xử lý OpenMP trên macOS và sau rất lâu mới gửi PR đầu tiên cho kho này