SDF, MSDF, Slug hay Texture Atlas: Chọn thuật toán render chữ trên GPU như thế nào?

Công nghệ30 tháng 9, 2026·12 phút đọc

Bài viết so sánh chi tiết năm phương pháp render văn bản trên GPU: texture atlas bitmap, SDF, MSDF, tessellation (Loop-Blinn, NV_path_rendering, Pathfinder, Rive) và Slug. Mỗi kỹ thuật có điểm mạnh riêng, nhưng Slug — thuật toán của Eric Lengyel vừa được đưa vào phạm vi công cộng năm 2026 — nổi bật nhờ render trực tiếp từ đường viền Bezier, giữ chữ sắc nét ở mọi kích thước và mọi góc nhìn 3D.

SDF, MSDF, Slug hay Texture Atlas: Chọn thuật toán render chữ trên GPU như thế nào?

Chữ trông có vẻ đơn giản cho đến khi bạn phải tự vẽ nó. Một ký tự không phải là một bức ảnh, mà là một tập hợp các đường viền: những vòng kín gồm đoạn thẳng và đường cong Bezier, được tô kín theo một quy tắc winding nhất định. Vẽ chúng trên CPU thành bitmap là bài toán đã có lời giải từ lâu. Nhưng vẽ trên GPU, sắc nét, ở mọi kích thước, dưới mọi phép biến đổi 3D, trong khi nội dung văn bản thay đổi mỗi khung hình — đó lại là câu chuyện hoàn toàn khác.

Hầu hết các engine né tránh phiên bản khó bằng cách nướng (bake) sẵn các glyph vào texture từ trước và chấp nhận những đánh đổi đi kèm.

Vì sao render glyph lại khó?

Mọi font có thể mở rộng (scalable font) đều lưu mỗi glyph dưới dạng đường viền vector. TrueType dùng đường cong Bezier bậc hai, OpenType với CFF dùng đường cong bậc ba, và cả hai đều xen lẫn các đoạn thẳng. Phần bên trong của ký tự được xác định bởi quy tắc fill — thường là quy tắc nonzero winding: bắn một tia từ điểm ảnh, đếm số lần đường viền cắt qua tia đó, nếu winding number khác 0 thì điểm ảnh nằm trong ký tự.

Renderer phải làm ba việc cùng lúc và phải làm thật nhanh:

  • Tô đúng phần bên trong ký tự
  • Tạo ra các cạnh khử răng cưa (antialiasing) sạch sẽ
  • Giữ độ sắc nét bất kể glyph cao 8 pixel trong menu hay phủ kín màn hình trên một billboard xoay theo phối cảnh

Trên CPU, bạn chỉ cần rasterize mỗi glyph một lần ở kích thước đích là xong. Trên GPU, bạn muốn vẽ hàng nghìn glyph mỗi khung hình, ở tỷ lệ tùy ý, lý tưởng nhất là không phải rasterize lại bất cứ thứ gì. Chính ràng buộc đó định hình mọi đánh đổi của các kỹ thuật dưới đây.

Phương pháp 1: Texture atlas (glyph bitmap)

Đây là cách lâu đời nhất và vẫn phổ biến nhất. Rasterize mỗi glyph một lần, ở một kích thước, vào một texture dùng chung gọi là atlas, sau đó vẽ từng ký tự trên màn hình dưới dạng một quad có gắn texture, lấy mẫu đúng ô của nó.

Cách này nhanh, dễ chuyển đổi nền tảng và chạy được trên bất cứ thứ gì có đơn vị xử lý texture — đó là lý do nó có mặt ở khắp nơi.

Vấn đề xuất hiện ngay khi bạn thay đổi tỷ lệ. Phóng to quá kích thước đã nướng, glyph biến thành các điểm ảnh mờ hoặc vỡ khối, vì bạn đang phóng đại một bitmap. Thu nhỏ thì sinh hiện tượng nhấp nháy (shimmer) và mất nét chân chữ trừ khi bạn nướng sẵn các cấp mipmap. Mỗi kích thước muốn sắc nét lại cần một atlas riêng. Mỗi ngôn ngữ lại là một vấn đề mới: atlas tiếng Latinh thì nhỏ, nhưng tiếng Trung, tiếng Nhật, tiếng Hàn có hàng chục nghìn glyph, nướng hết ở nhiều kích thước là thảm họa về bộ nhớ. Và một bitmap không hề biết nó đang được nhìn theo phối cảnh, nên chữ dán lên bề mặt 3D trông mềm và mờ.

Phương pháp 2: Signed Distance Field (SDF)

Valve giới thiệu giải pháp đã gánh vác cả ngành công nghiệp suốt một thập kỷ. Công trình SIGGRAPH 2007 của Chris Green, "Improved Alpha-Tested Magnification for Vector Textures and Special Effects", không lưu điểm ảnh của glyph mà lưu một signed distance field: mỗi texel giữ khoảng cách đến cạnh gần nhất, dương nếu ở trong, âm nếu ở ngoài. Trong shader, bạn lấy mẫu trường đó và ngưỡng hóa tại mức 0.

Vì khoảng cách nội suy mượt mà, bạn có thể phóng một texture SDF nhỏ lên rất lớn mà vẫn có cạnh sạch, đồng thời khử răng cưa rẻ bằng cách làm mềm ngưỡng. Một texture nhỏ, độc lập độ phân giải trong giới hạn hợp lý, một shader rẻ. Trong một thời gian dài, đây là mặc định cho chữ UI sắc nét và HUD trong game, và đến nay vẫn đúng trên phần cứng yếu.

Nhưng SDF vẫn là một texture đã nướng, lấy mẫu ở độ phân giải cố định, và nó "nói dối" về các góc nhọn. Một góc nhọn là điểm gián đoạn trong trường khoảng cách, và phép nội suy song tuyến sẽ bo tròn nó. Mọi góc cứng trên chữ — đỉnh chữ "A", khấc chữ "K" — đều bị làm mềm. Khi phóng đại đủ xa, hoặc khi glyph nhỏ đến mức trường chỉ rộng vài texel, các nét mảnh sẽ đứt gãy và chi tiết bị nhòe.

Phương pháp 3: Multi-channel Signed Distance Field (MSDF)

Công trình của Viktor Chlumsky, từ luận văn năm 2015 và bài báo 2018 "Improved Corners with Multi-Channel Signed Distance Fields", khắc phục vấn đề góc nhọn. Thay vì một kênh khoảng cách, MSDF lưu ba kênh ở đỏ, xanh lá và xanh dương, mỗi kênh mã hóa khoảng cách đến một tập cạnh khác nhau, được chọn sao cho các góc nhọn vẫn tồn tại. Trong shader, bạn lấy trung vị (median) của ba kênh.

Thủ thuật trung vị tái tạo góc gần như hoàn hảo, nên glyph MSDF vẫn sắc nét ở mức phóng đại mà SDF đã nhòe thành bùn. MSDF hiện là điểm cân bằng lý tưởng cho nhiều đội ngũ, và msdfgen của Chlumsky theo giấy phép MIT, được ứng dụng rộng rãi. Nếu bạn cần chữ sắc nét, co giãn tốt và chấp nhận nướng atlas, đây là lựa chọn xuất sắc.

Tuy nhiên nó vẫn là atlas, với mọi chi phí kèm theo. Bạn phải nướng từng glyph ở độ phân giải chọn trước, nên văn bản động, do người dùng nhập, hay bộ glyph khổng lồ như CJK vẫn đòi hỏi pipeline nướng và ngân sách bộ nhớ. Quá trình sinh tốn kém hơn SDF thường. Ở kích thước rất nhỏ, bạn vẫn lấy mẫu quá ít texel để giữ chi tiết mảnh. Tra cứu ba kênh tốn băng thông hơn một kênh.

Phương pháp 4: Tessellation và coverage (Loop-Blinn, NV_path_rendering, Pathfinder, Rive)

Một họ phương pháp khác bỏ hẳn texture và biến đường viền thành hình học để GPU rasterize.

  • Loop-Blinn đưa các tam giác cong vào GPU và dùng shader discard theo từng điểm ảnh để giữ lại phần bên trong mỗi đường Bezier bậc hai, kết hợp stencil buffer để giải quyết winding. Thanh lịch, nhưng khử răng cưa đáng tin cậy thực sự rất khó nếu không dùng những thủ thuật làm giảm chất lượng.
  • Stencil-then-cover, được NVIDIA công bố dưới dạng extension NV_path_rendering, vẽ đường dẫn vào stencil buffer trong một lượt, rồi phủ lên trong lượt thứ hai. Chất lượng cao nhưng phụ thuộc extension của nhà cung cấp và đường đi phần cứng cụ thể.
  • Pathfinder tessellate các cạnh thành vi tam giác, tính diện tích hình thang có dấu theo từng điểm ảnh và tích lũy coverage trong một compute pass. Dựa trên tile và nhanh trên GPU hiện đại.
  • Renderer của Rive, mã nguồn mở từ năm 2024, rút gọn các đường vector có khử răng cưa thành các mảnh tam giác riêng biệt và rasterize chúng qua pipeline song song hóa cực mạnh với pixel local storage, đạt 120 fps cho đồ họa vector động.

Họ phương pháp này thực sự độc lập độ phân giải và với đồ họa vector động có thiết kế, thường là câu trả lời đúng. Rive đặc biệt được xây dựng cho tác phẩm đồ họa chuyển động. Cái giá phải trả là chính việc tessellate — phải làm lại khi hình học thay đổi — sự phình to hình học với glyph phức tạp, khó khử răng cưa giải tích sạch sẽ, và đôi khi phụ thuộc tính năng hay extension phần cứng cụ thể.

Phương pháp 5: Slug — render thẳng từ đường viền

Slug bỏ qua atlas và tessellation mỗi khung hình, giữ glyph dưới dạng danh sách các đường cong Bezier bậc hai và đoạn thẳng lưu trong một buffer GPU nhỏ. Song song đó, Slug xây một cấu trúc tăng tốc nhẹ theo từng glyph, chia glyph thành các dải ngang, để một điểm ảnh chỉ phải xét vài đường cong gần nó thay vì toàn bộ đường viền.

Sau đó nó giải coverage trực tiếp trong fragment shader. Với mỗi điểm ảnh, shader thực chất bắn một tia, tìm nơi tia cắt các đường Bezier lân cận, và đếm số lần cắt để tính winding number, từ đó ra coverage. Phần khó nhất, và cũng là "nước sốt bí mật" của Lengyel, là một phép kiểm tra ông gọi là root eligibility: một quy tắc chính xác xác định giao điểm nào giữa đường cong và tia được tính, để phép toán winding chuẩn xác tại các điểm đầu chung nơi các đường cong gặp nhau — nơi cách tiếp cận ngây thơ sinh ra vết nứt hoặc đếm trùng. Vì shader giải phương trình đường cong bằng giải tích thay vì lấy mẫu một trường đã nướng, nó cho coverage chính xác và khử răng cưa sạch ở mọi tỷ lệ.

Không có độ phân giải nướng sẵn, nên cùng một glyph sắc như dao cạo ở 6 pixel hay 6000 pixel, và vẫn sắc dưới mọi phép biến đổi 2D lẫn 3D, kể cả phối cảnh, vì coverage được tính theo từng điểm ảnh sau biến đổi. Không có atlas, nên một trăm nghìn glyph CJK chỉ tốn lượng dữ liệu đường viền tương đương một font, chứ không phải một atlas cỡ video. Văn bản có thể thay đổi mỗi khung hình mà không tốn chi phí nướng — đúng thứ bạn cần cho dữ liệu trực tiếp, dữ liệu người dùng nhập và nội dung bản địa hóa.

Điều này cực kỳ quan trọng khi bạn không thể dự đoán trước văn bản sẽ được nhìn như thế nào.

Atlas, SDF và MSDF đều nướng một độ phân giải cố định từ trước, ngầm giả định một khoảng kích thước hiển thị và góc nhìn hữu hạn. Khi mối quan hệ giữa mặt phẳng chữ và camera không biết trước — camera 3D tự do, zoom tùy ý, cận cảnh, hay góc xiên gắt — các xấp xỉ nướng sẵn đó sụp đổ. Bạn không thể cấp phát đủ độ phân giải cho mọi góc nhìn khả dĩ mà không làm dung lượng bùng nổ. Slug tính coverage bằng giải tích, theo từng điểm ảnh, sau biến đổi, nên nó vẫn chính xác bất kể người xem ở gần, ở xa hay nhìn xiên đến đâu.

So sánh trực tiếp

Tiêu chíAtlas bitmapSDFMSDFTessellation / RiveSlug
Sắc nét ở mọi tỷ lệKhôngMột phầnPhần lớnCóCó
Góc nhọnChỉ ở cỡ nướngKhôngCóCóCó
Kích thước rất nhỏNướng theo cỡYếuKhá hơnTốtTốt
Bộ nhớ cho bộ glyph lớn (CJK)Rất caoCaoCaoThấpTrung bình
Văn bản động/thay đổiNướng lạiNướng lạiNướng lạiTessellate lạiMiễn phí
3D và phối cảnhMờTạmTạmTốtXuất sắc
Đồ họa vector động nhiềuKhôngKhôngKhôngXuất sắc (Rive)Tốt
Chạy trên GPU yếu/cũXuất sắcXuất sắcTốtTùyCần shader đủ mạnh
Độ phức tạp triển khaiThấpThấpTrung bìnhCaoTrung bình đến cao

Vậy nên chọn cái nào?

Không có một người thắng duy nhất — chỉ có công cụ đúng cho từng việc.

  • Chọn Slug(horn) khi bạn cần chữ sắc nét ở mọi tỷ lệ và dưới biến đổi 3D lẫn phối cảnh (VR/AR/xR), khi bộ glyph khổng lồ hoặc động, khi văn bản thay đổi liên tục, hoặc khi render UI vector hỗn hợp vào pipeline thời gian thực. Đây là các buồng lái kính GIS, nhãn mô phỏng thị giác, màn hình không gian vũ trụ, lớp phủ AR và mọi giao diện phải giữ được độ đọc rõ khi di chuyển.
  • Chọn MSDF khi bạn muốn chữ sắc nét, co giãn tốt, có thể nướng atlas từ trước và hài lòng với dải phần cứng rộng. Đây là mặc định tốt cho HUD game đơn giản và UI ứng dụng.
  • Chọn SDF thường khi phần cứng hạn chế, văn bản khá tĩnh và bạn chấp nhận góc bị bo mềm.
  • Chọn atlas bitmap khi văn bản cố định kích thước trên UI cố định và bạn muốn thứ đơn giản, dễ chuyển nền tảng nhất có thể chạy được.
  • Chọn Rive hoặc renderer tessellation khi công việc là đồ họa vector được thiết kế có chuyển động, không phải chủ yếu là chữ.

Vài nét về bối cảnh tại Việt Nam

Với các đội phát triển game mobile và ứng dụng tại Việt Nam, MSDF và texture atlas vẫn là lựa chọn thực dụng nhất vì chạy tốt trên dải thiết bị Android rộng và không đòi hỏi shader phức tạp. Tuy nhiên, khi các studio chuyển sang làm nội dung AR/VR, ứng dụng bản đồ số, hoặc giao diện đa ngôn ngữ có tiếng Trung, tiếng Nhật, tiếng Hàn, bài toán bộ nhớ atlas và độ sắc nét dưới góc nhìn 3D sẽ sớm trở thành điểm nghẽn thực sự. Việc Slug được đưa vào phạm vi công cộng từ tháng 3 năm 2026 mở ra cơ hội để các đội ngũ trong nước tự triển khai kỹ thuật này mà không lo rào cản bằng sáng chế.

Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗