Kết xuất đường viền, trừ khi bạn chỉ hiển thị tổng cộng một chục ký tự, vẫn là "không đi" do số lượng đỉnh cần thiết cho mỗi ký tự cho độ cong gần đúng. Mặc dù đã có các cách tiếp cận để đánh giá các đường cong bezier trong trình đổ bóng pixel, nhưng chúng không bị khử răng cưa một cách dễ dàng, điều này không quan trọng bằng cách sử dụng một tứ giác có kết cấu bản đồ khoảng cách và đánh giá các đường cong trong trình đổ bóng vẫn đắt hơn nhiều so với mức cần thiết.
Sự đánh đổi tốt nhất giữa "nhanh" và "chất lượng" vẫn là các quads có kết cấu với kết cấu trường khoảng cách đã ký. Nó rất chậm hơn một chút so với sử dụng một quad có kết cấu bình thường, nhưng không quá nhiều. Mặt khác, chất lượng là ở một sân bóng hoàn toàn khác. Các kết quả thực sự tuyệt vời, nó nhanh như bạn có thể nhận được, và các hiệu ứng như phát sáng cũng rất dễ dàng để thêm vào. Ngoài ra, kỹ thuật có thể được hạ cấp độc đáo xuống phần cứng cũ, nếu cần.
Xem giấy Valve nổi tiếng về kỹ thuật.
Kỹ thuật này về mặt khái niệm tương tự như cách các bề mặt ẩn (siêu dữ liệu và như vậy) hoạt động, mặc dù nó không tạo ra đa giác. Nó chạy hoàn toàn trong pixel shader và lấy khoảng cách được lấy mẫu từ kết cấu làm hàm khoảng cách. Mọi thứ trên ngưỡng đã chọn (thường là 0,5) là "trong", mọi thứ khác là "hết". Trong trường hợp đơn giản nhất, trên phần cứng không có khả năng tạo bóng 10 năm tuổi, đặt ngưỡng kiểm tra alpha thành 0,5 sẽ thực hiện điều đó chính xác (mặc dù không có hiệu ứng đặc biệt và khử răng cưa).
Nếu một người muốn thêm một chút trọng lượng cho phông chữ (giả đậm), một ngưỡng nhỏ hơn một chút sẽ thực hiện thủ thuật mà không sửa đổi một dòng mã (chỉ cần thay đổi đồng phục "font_ weight" của bạn). Đối với hiệu ứng phát sáng, người ta chỉ cần coi mọi thứ trên một ngưỡng là "trong" và mọi thứ trên ngưỡng khác (nhỏ hơn) là "ngoài, nhưng trong phát sáng" và LERP giữa hai. Khử răng cưa hoạt động tương tự.
Bằng cách sử dụng giá trị khoảng cách được ký 8 bit thay vì một bit, kỹ thuật này tăng độ phân giải hiệu quả của bản đồ kết cấu của bạn lên 16 lần cho mỗi chiều (thay vì đen và trắng, tất cả các sắc thái có thể được sử dụng, do đó chúng tôi có 256 lần thông tin sử dụng cùng một bộ lưu trữ). Nhưng ngay cả khi bạn phóng to vượt xa 16 lần, kết quả vẫn có vẻ khá chấp nhận được. Các đường thẳng dài cuối cùng sẽ trở nên hơi gượng gạo, nhưng sẽ không có các tạo tác lấy mẫu "khối" điển hình.
Bạn có thể sử dụng một shader hình học để tạo ra các quads trong số các điểm (giảm băng thông bus), nhưng thành thật mà nói thì mức tăng khá ít. Điều này cũng đúng với kết xuất ký tự được mô tả như được mô tả trong GPG8. Chi phí đầu tư chỉ được khấu hao nếu bạn có nhiều văn bản để vẽ. Những lợi ích, theo tôi, không liên quan đến sự phức tạp thêm và không hạ cấp. Thêm vào đó, bạn bị giới hạn bởi số lượng thanh ghi không đổi hoặc bạn phải đọc từ một đối tượng bộ đệm kết cấu, không tối ưu cho sự kết hợp bộ đệm (và mục đích là tối ưu hóa để bắt đầu!).
Một bộ đệm đỉnh đơn giản, đơn giản cũ cũng nhanh như vậy (có thể nhanh hơn) nếu bạn lên lịch tải lên trước một chút và sẽ chạy trên mọi phần cứng được xây dựng trong 15 năm qua. Và, nó không giới hạn ở bất kỳ số lượng ký tự cụ thể nào trong phông chữ của bạn cũng như số lượng ký tự cụ thể để hiển thị.
Nếu bạn chắc chắn rằng bạn không có nhiều hơn 256 ký tự trong phông chữ của mình, các mảng kết cấu có thể đáng xem xét để loại bỏ băng thông xe buýt theo cách tương tự như tạo ra các hình tứ giác từ các điểm trong trình đổ bóng hình học. Khi sử dụng một kết cấu mảng, tọa độ kết cấu của tất cả các hình tứ giác có tọa độ giống hệt nhau, không đổi s
và t
tọa độ và chỉ khác nhau về r
tọa độ, bằng với chỉ số ký tự để hiển thị.
Nhưng giống như các kỹ thuật khác, mức tăng dự kiến là không đáng kể với chi phí không tương thích với phần cứng thế hệ trước.
Có một công cụ tiện dụng của Jonathan Dummer để tạo họa tiết khoảng cách: trang mô tả
Cập nhật:
Như gần đây đã chỉ ra trong Vertex Pulling có thể lập trình (D. Rákos, "OpenGL Insights", trang 239), không có độ trễ hoặc chi phí đáng kể nào liên quan đến việc kéo dữ liệu đỉnh được lập trình từ trình tạo bóng trên các thế hệ GPU mới nhất, so với làm tương tự bằng cách sử dụng chức năng cố định tiêu chuẩn.
Ngoài ra, các thế hệ GPU mới nhất có bộ nhớ L2 mục đích chung có kích thước hợp lý hơn (ví dụ 1536kiB trên nvidia Kepler), do đó, người ta có thể mong đợi vấn đề truy cập không nhất quán khi kéo các offset ngẫu nhiên cho các góc tứ giác từ kết cấu bộ đệm ít hơn vấn đề.
Điều này làm cho ý tưởng kéo dữ liệu không đổi (chẳng hạn như kích thước quad) từ kết cấu bộ đệm hấp dẫn hơn. Do đó, việc triển khai giả thuyết có thể làm giảm chuyển PCIe và bộ nhớ, cũng như bộ nhớ GPU, xuống mức tối thiểu với cách tiếp cận như sau:
- Chỉ tải lên một chỉ mục ký tự (mỗi ký tự được hiển thị) làm đầu vào duy nhất cho trình tạo bóng đỉnh truyền vào chỉ mục này
gl_VertexID
và khuếch đại lên 4 điểm trong trình tạo bóng hình học, vẫn có chỉ mục ký tự và id đỉnh (điều này sẽ là "gl_primitiveID có sẵn trong shader đỉnh") làm thuộc tính duy nhất và nắm bắt điều này thông qua phản hồi chuyển đổi.
- Điều này sẽ nhanh chóng, bởi vì chỉ có hai thuộc tính đầu ra (nút cổ chai chính trong GS) và nó gần với "no-op" nếu không trong cả hai giai đoạn.
- Ràng buộc một kết cấu bộ đệm chứa, đối với mỗi ký tự trong phông chữ, các vị trí đỉnh của hình tứ giác có kết cấu so với điểm gốc (về cơ bản là "số liệu phông chữ"). Dữ liệu này có thể được nén thành 4 số trên mỗi quad bằng cách lưu trữ phần bù của đỉnh bên trái phía dưới và mã hóa chiều rộng và chiều cao của hộp căn chỉnh trục (giả sử một nửa số float, đây sẽ là 8 byte bộ đệm không đổi cho mỗi ký tự - một phông chữ 256 ký tự điển hình có thể phù hợp hoàn toàn với 2kiB của bộ đệm L1).
- Đặt đồng phục cho đường cơ sở
- Ràng buộc một kết cấu đệm với độ lệch ngang. Những thể có lẽ thậm chí được tính toán trên GPU, nhưng nó là dễ dàng hơn và hiệu quả hơn với loại điều trên CPU, vì nó là một hoạt động đúng tuần tự và không phải ở tất cả tầm thường (nghĩ về kerning). Ngoài ra, nó sẽ cần một thông tin phản hồi khác, đó sẽ là một điểm đồng bộ hóa khác.
- Kết xuất dữ liệu được tạo trước đó từ bộ đệm phản hồi, trình tạo bóng đỉnh kéo phần bù ngang của điểm gốc và phần bù của các đỉnh góc từ các đối tượng bộ đệm (sử dụng id nguyên thủy và chỉ mục ký tự). ID đỉnh ban đầu của các đỉnh được gửi bây giờ là "ID nguyên thủy" của chúng tôi (hãy nhớ rằng GS đã biến các đỉnh thành hình tứ giác).
Như thế này, một cách lý tưởng có thể giảm 75% băng thông đỉnh yêu cầu (khấu hao), mặc dù nó chỉ có thể hiển thị một dòng duy nhất. Nếu một người muốn có thể kết xuất nhiều dòng trong một cuộc gọi vẽ, người ta sẽ cần thêm đường cơ sở vào kết cấu bộ đệm, thay vì sử dụng đồng phục (làm cho băng thông tăng nhỏ hơn).
Tuy nhiên, ngay cả khi giả định giảm 75% - vì dữ liệu đỉnh để hiển thị số lượng văn bản "hợp lý" chỉ ở đâu đó khoảng 50-100kiB (thực tế là bằng khôngvới GPU hoặc bus PCIe) - Tôi vẫn nghi ngờ rằng sự phức tạp được thêm vào và mất khả năng tương thích ngược thực sự đáng để xử lý. Giảm 0% vẫn chỉ là 0. Tôi đã thừa nhận không thử cách tiếp cận trên, và sẽ cần nhiều nghiên cứu hơn để đưa ra một tuyên bố thực sự đủ điều kiện. Tuy nhiên, trừ khi ai đó có thể chứng minh sự khác biệt hiệu suất thực sự đáng kinh ngạc (sử dụng số lượng văn bản "bình thường", chứ không phải hàng tỷ ký tự!), Quan điểm của tôi vẫn cho rằng đối với dữ liệu đỉnh, bộ đệm đỉnh đơn giản, đơn giản là đủ tốt được coi là một phần của "giải pháp hiện đại". Nó đơn giản và dễ hiểu, nó hoạt động, và nó hoạt động tốt.
Đã tham khảo " Thông tin chi tiết về OpenGL " ở trên, cũng đáng để chỉ ra chương "Kết xuất hình dạng 2D theo trường khoảng cách" của Stefan Gustavson, giải thích rất rõ về kết xuất trường khoảng cách.
Cập nhật 2016:
Trong khi đó, tồn tại một số kỹ thuật bổ sung nhằm loại bỏ các vật phẩm làm tròn góc trở nên đáng lo ngại ở độ phóng đại cực lớn.
Một cách tiếp cận chỉ đơn giản là sử dụng các trường khoảng cách giả thay vì các trường khoảng cách (sự khác biệt là khoảng cách là khoảng cách ngắn nhất không phải với phác thảo thực tế, mà là phác thảo hoặc một đường tưởng tượng nhô ra ngoài rìa). Điều này có phần tốt hơn và chạy ở cùng tốc độ (shader giống hệt nhau), sử dụng cùng một lượng bộ nhớ kết cấu.
Một cách tiếp cận khác sử dụng trung vị ba trong một chi tiết kết cấu ba kênh và triển khai có sẵn tại github . Điều này nhằm mục đích là một cải tiến đối với và hoặc các vụ hack được sử dụng trước đây để giải quyết vấn đề. Chất lượng tốt, hơi, hầu như không đáng chú ý, chậm hơn, nhưng sử dụng bộ nhớ kết cấu nhiều gấp ba lần. Ngoài ra, các hiệu ứng phụ (ví dụ: phát sáng) khó hơn để có được đúng.
Cuối cùng, việc lưu trữ các đường cong bezier thực tế tạo nên các ký tự và đánh giá chúng trong một shader mảnh đã trở nên thiết thực , với hiệu suất kém hơn một chút (nhưng không đến nỗi nó là một vấn đề) và kết quả tuyệt vời ngay cả ở độ phóng đại cao nhất.
Bản demo WebGL hiển thị một tệp PDF lớn với kỹ thuật này trong thời gian thực có sẵn tại đây .