EDIT: Xin vui lòng xem câu trả lời khác của tôi với một giải pháp cụ thể.
Tôi thực sự đã giải quyết vấn đề chính xác này hơn một năm trước cho luận án thạc sĩ của mình. Trong bài viết của Valve, họ cho thấy rằng bạn có thể VÀ hai trường khoảng cách để đạt được điều này, hoạt động miễn là bạn chỉ có một góc lồi. Đối với các góc lõm, bạn cũng cần thao tác OR. Anh chàng này thực sự đã phát triển một số hệ thống tối nghĩa để chuyển đổi giữa hai hoạt động bằng cách sử dụng bốn kênh kết cấu.
Tuy nhiên, có một thao tác đơn giản hơn nhiều có thể tạo điều kiện thuận lợi cho cả AND và OR tùy thuộc vào tình huống và đây là ý tưởng chính của luận án của tôi: trung vị của ba . Về cơ bản, bạn sử dụng chính xác ba kênh (lý tưởng cho RGB), hoàn toàn có thể hoán đổi cho nhau và kết hợp chúng bằng cách sử dụng thao tác trung bình (chọn giá trị trung bình trong số ba kênh).
Để thực hiện khử răng cưa, chúng ta không làm việc chỉ với các giá trị booleans, nhưng các giá trị dấu phẩy động và hoạt động AND trở thành mức tối thiểu và OR trở thành mức tối đa của hai giá trị. Trung vị của ba thực sự có thể làm cả hai: nếu a < b , for ( a , a , b ), trung vị là tối thiểu và với ( a , b , b ), đó là mức tối đa.
Quá trình kết xuất vẫn cực kỳ đơn giản. Toàn bộ shader mảnh bao gồm khử răng cưa có thể trông giống như thế này:
int main() {
// Bilinear sampling of the distance field
vec3 s = texture2D(sdf, p).rgb;
// Acquire the signed distance
float d = median(s.r, s.g, s.b) - 0.5;
// Weight between inside and outside (anti-aliasing)
float w = clamp(d/fwidth(d) + 0.5, 0.0, 1.0);
// Combining the background and foreground color
gl_FragColor = mix(outsideColor, insideColor, w);
}
Vì vậy, sự khác biệt duy nhất so với phương pháp ban đầu là tính toán trung vị ngay sau khi lấy mẫu kết cấu. Bạn sẽ phải thực hiện chức năng trung bình, có thể được thực hiện chỉ với 4 thao tác tối đa / tối đa .
Bây giờ tất nhiên, câu hỏi là, làm thế nào để tôi xây dựng trường khoảng cách ba kênh như vậy?Và đây là phần khó khăn. Cách tiếp cận rõ ràng nhất mà tôi đã thực hiện lúc đầu là thực hiện phân tách hình dạng đầu vào / glyph thành ba thành phần, và sau đó tạo ra một trường khoảng cách thông thường từ mỗi thành phần. Các quy tắc cho phân rã này không phức tạp. Thứ nhất, khu vực có ít nhất 2 trên 3 kênh là bên trong. Sau đó, nếu bạn tưởng tượng đây là các kênh màu RGB, các góc lồi phải được tạo bằng màu thứ cấp và hai thành phần chính của nó tiếp tục hướng ra ngoài. Các góc lõm là nghịch đảo: Hai màu thứ cấp bao quanh màu chính chung của chúng và phần nêm giữa nơi cả hai cạnh tiếp tục hướng vào trong là màu trắng. Tôi cũng thấy rằng một số phần đệm là cần thiết trong đó hai màu chính hoặc hai màu phụ sẽ chạm vào nhau để tránh tạo tác (ví dụ, trong nét giữa của chữ "N"
Hình ảnh sau đây là một ví dụ phân tách được tạo bởi chương trình từ luận án của tôi:
Cách tiếp cận này tuy nhiên có một số nhược điểm. Một trong số đó là các hiệu ứng đặc biệt, như đường viền và bóng sẽ không còn hoạt động chính xác. Fortunatelly, tôi cũng đã đưa ra một phương pháp thứ hai thanh lịch hơn nhiều, tạo ra các trường khoảng cách trực tiếp và thậm chí hỗ trợ tất cả các hiệu ứng đồ họa. Nó cũng được bao gồm trong luận án của tôi và như vậy cũng đã hơn một năm tuổi. Tôi sẽ không cung cấp thêm bất kỳ chi tiết nào ngay bây giờ, bởi vì hiện tại tôi đang viết một bài báo mô tả kỹ thuật thứ hai này một cách chi tiết, nhưng tôi sẽ đăng nó ở đây ngay khi nó kết thúc.
Dù sao, đây là một ví dụ về sự khác biệt về chất lượng. Độ phân giải kết cấu là giống nhau trong mỗi hình ảnh, nhưng hình bên trái sử dụng kết cấu thông thường, hình giữa sử dụng trường khoảng cách thông thường và hình bên phải sử dụng trường khoảng cách ba kênh của tôi. Chi phí hoạt động chỉ là sự khác biệt giữa lấy mẫu kết cấu RGB so với đơn sắc.