So Sánh Các Định Dạng Nén Bản Đồ Pháp Tuyến - nói dối e blog

So Sánh Các Định Dạng Nén Bản Đồ Pháp Tuyến

Vài ngày qua tôi liên tục bận rộn với việc bổ sung hỗ trợ định dạng ASTC cho bản đồ pháp tuyến trên thư viện bgfx. Trong không gian tiếp tuyến, các vector pháp tuyến được chuẩn hóa và thành phần Z luôn mang giá trị dương. Điều này cho phép chúng ta chỉ cần lưu trữ hai thành phần X và Y, thành phần Z sẽ được tính toán lại tại thời gian chạy.

Tuy nhiên phương pháp này tồn tại một vấn đề: khi thực hiện nội suy tuyến tính qua bộ lọc texture, giá trị Z tính toán được có thể sai lệch đáng kể so với thực tế. Giải pháp phổ biến là sử dụng phép chiếu cầu để lưu trữ các thành phần XY, giúp giảm sai số trên trục Z. Bạn có thể tham khảo chi tiết trong bài viết “Real-Time Normal Map DXT Compression” của NVIDIA.

Ban đầu phần cứng GPU không hỗ trợ nén texture hai kênh, vì vậy Id Software đã dùng thủ thuật với định dạng DXT5 - lưu một kênh trong thành phần G của RGB và kênh còn lại trong kênh alpha. Về sau định dạng EAC_RG11 ra đời đã hỗ trợ chính thức việc nén texture hai kênh.

Mặc dù ASTC không có chế độ chuyên dụng cho hai kênh, nhưng nhờ cơ chế phân bổ trọng số thông minh của encoder, định dạng này có thể tối ưu để giảm sai số trên hai kênh thông tin. Hiện tại công cụ nén texture tích hợp sẵn trong bgfx chưa hỗ trợ đầy đủ các tham số cần thiết, đây chính là công việc tôi đang hoàn thiện.

Việc bổ sung hỗ trợ ASTC cho bgfx bắt nguồn từ dự án Football Manager. Vài tháng trước tôi đã tạo một issue trên kho mã nguồn để đề xuất cải tiến, nhưng có vẻ tác giả chính đang bận rộn nên chưa phản hồi. Gần đây khi dự án của chúng tôi cần port lên nền tảng di động (với yêu cầu bắt buộc sử dụng bản đồ pháp tuyến nén để tiết kiệm bộ nhớ), tôi quyết định tự triển khai. Điều thú vị là việc này đã “đánh thức” tác giả chính, hiện anh ấy đã bắt tay vào hoàn thiện phần hỗ trợ này.

Một phát hiện bất ngờ khác: PR tôi gửi cho dự án bimg居然 có thể hợp nhất chéo kho sang dự án astc_encoder mà vẫn giữ nguyên thông tin tác giả và thời gian commit. Đây là lần đầu tôi biết Git có tính năng hợp nhất patch chéo kho như vậy!

Với việc bắt đầu công việc này, tôi có thêm thời gian so sánh chất lượng giữa các định dạng nén. Trong lĩnh vực nén ảnh mất mát, PSNR (Peak Signal-to-Noise Ratio) là chỉ số đo chất lượng phổ biến - giá trị càng cao chất lượng càng tốt. Tuy nhiên không nên quá cứng nhắc với PSNR, một số công cụ như ASTC và ETC cung cấp tùy chọn “percep” (perceptual) với chất lượng hình ảnh chủ quan tốt hơn dù PSNR thấp hơn một chút. Đây cũng là tùy chọn mặc định của etcpack.

Tôi sử dụng các công cụ sau để thực hiện thử nghiệm:

  • NVIDIA Texture Tools cho định dạng DXT
  • ARM ASTC Encoder cho định dạng ASTC
  • Ericsson Texture Compression cho định dạng ETC

Đặc biệt, tài liệu hướng dẫn của ASTC Encoder có phần riêng về tối ưu hóa cho bản đồ pháp tuyến. Tôi sử dụng một texture pháp tuyến 2048x2048 từ kho tài nguyên công khai của Unity để làm vật liệu thử nghiệm.

Kết quả thử nghiệm:

Công cụ nén Định dạng Kênh bpp Tham số PSNR (dB)
nvcompress dxt1nm RGB 4 -nomips -normal -bc1n 27.484683
astcenc astc 6x5 RG 4.27 -t 4.0 -normal_psnr -thorough 29.670458
astcenc astc 4x4 RGB 8 -t 8.0 -thorough 33.238881
astcenc astc 5x4 RG 6.4 -t 6.0 -normal_psnr -thorough 33.839983
nvcompress dxt5nm RG 8 -nomips -normal -bc3n 34.518504
astcenc astc 4x4 RG 8 -t 8.0 -normal_percep -fast 35.779205
astcenc astc 4x4 RG 8 -t 8.0 -normal_psnr -fast 36.121064
astcenc astc 4x4 RG 8 -t 8.0 -normal_percep -thorough 37.030079
astcenc astc 4x4 RG 8 -t 8.0 -normal_psnr -thorough 37.403131
etcpack EAC_RG11 RG 8 -f RG 40.834371

Tất cả giá trị PSNR đều được tính toán bằng astcenc để đảm bảo công bằng, vì công cụ của NVIDIA chỉ xử lý hai kênh trong khi các công cụ khác khôi phục đầy đủ ba kênh. Tôi đã sử dụng ImageMagick để loại bỏ kênh blue trước khi tính toán.

Nhận định:

  • EAC_RG11 đạt chất lượng cao nhất nhưng tốc độ nén cực chậm (một ảnh 2048x2048 mất vài phút so với 1 giây của DXT). Tôi đã từng phát triển phiên bản tối ưu hóa giảm độ phức tạp từ O(n²) xuống O(n).
  • DXT có chất lượng kém nhất nhưng lại là định dạng lâu đời và phổ biến nhất.
  • ASTC thể hiện tính linh hoạt vượt trội: chỉ cần 6bpp đã đạt chất lượng tương đương DXT ở 8bpp. Các tùy chọn tối ưu hóa cho hai kênh mang lại cải thiện rõ rệt, đồng thời cho phép điều chỉnh chất lượng để giảm dung lượng (điều mà EAC không làm được).

Việc lựa chọn định dạng phụ thuộc vào yêu cầu cụ thể của từng dự án: nếu cần chất lượng cao tuyệt đối và chấp nhận tốc độ nén chậm, EAC_RG11 là lựa chọn tối ưu. Ngược lại, ASTC là giải pháp cân bằng hoàn hảo giữa chất lượng, tốc độ và tính linh hoạt.

0%