Góc nhọn với phông chữ trường khoảng cách đã ký


49

Các trường khoảng cách đã ký (SDF) đã được trình bày như một giải pháp nhanh chóng để đạt được kết xuất phông chữ độc lập với độ phân giải của Valve trong bài viết này .

Tôi đã có giải pháp Valve hoạt động nhưng tôi muốn duy trì độ sắc nét xung quanh các góc. Valve tuyên bố rằng phương pháp của họ có thể đạt được các góc sắc nét bằng cách sử dụng kênh kết cấu thứ hai ANDed với cơ sở thứ nhất, nhưng thiếu để giải thích cách tạo kênh thứ hai này.

Trong thực tế, có rất nhiều chi tiết thực hiện còn sót lại trong bài viết này.

Tôi muốn biết liệu có ai trong số các bạn có thể chỉ cho tôi một hướng để có được kết xuất phông chữ SDF với các góc nhọn hay không.


Như một vấn đề của thực tế, Adam đã đăng mã nguồn trên shadertoy. Đây là liên kết: shadertoy.com/view/ltXSDB
Felipe Lira

Bạn đã làm tôi phấn khích. Anh ấy đã đăng những thứ bezier trên shadertoy nhưng không phải những thứ về khoảng cách kết cấu!
Alan Wolfe

@AlanWolfe Tôi nghĩ rằng anh ấy đã làm chỉ cho các đường cong bezier. Tôi không chắc nỗ lực cần thiết để tích hợp điều này vào lib kết xuất ttf. Khi tôi có thời gian tôi sẽ xem xét nó.
Felipe Lira

Có vẻ như anh ta có một số nước sốt ma thuật ở phía thực sự lưu trữ và lấy khoảng cách từ một kết cấu. Không có kết cấu trong trò chơi, các ví dụ shadertoy bị thiếu phần đó của phương trình.
Alan Wolfe

Đến bữa tiệc muộn nhưng chủ đề cũ hơn từ reddit này có rất nhiều thông tin về các phương pháp khác nhau để cải thiện độ sắc nét của kết xuất dựa trên SDF: reddit.com/r/gamedev/comments/2879jd/
trộm

Câu trả lời:


7

Adam Simmons đã thực hiện một số công việc thú vị trong lĩnh vực này. Tôi không biết cụ thể anh ta đạt được nó như thế nào, nhưng kết xuất véc tơ dựa trên SDF của anh ta là sắc nét nhất tôi từng thấy trong thực tế ngoài Valve. http://twitter.com/adamjsimmons/status/611677036545863680


Tất nhiên tôi không có tất cả các chi tiết, nhưng dường như người này chỉ sử dụng trường giả khoảng cách thay cho trường thông thường, điều này đã được Qin, McCool và Kaplan chứng minh trong một bài báo năm 2006. Các glyphs vector được ánh xạ kết cấu thời gian thực ", cũng được tham chiếu trong bài báo của Valve. Nó chỉ ảnh hưởng đến các phần tử của phác thảo và không làm gì để cải thiện sự xuất hiện của các góc. Tôi nghi ngờ lý do nó trông sắc nét là bởi vì anh ta sử dụng kết cấu trường khoảng cách lớn không chính xác. Tôi có thể sai mặc dù.
Detheroc

69

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:

Phân hủy đa kênh của glyphs

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.

nhập mô tả hình ảnh ở đây


5
Câu trả lời đầu tiên tuyệt vời, chào mừng bạn đến với Đồ họa máy tính SE! :) Luận án của bạn có công khai không? (Hoặc sẽ là sau khi bạn nói xong giấy?) Nếu vậy có lẽ cũng rất hữu ích để liên kết đến đó.
Martin Ender

Nó được cho là có sẵn công khai, nhưng có vẻ như trường chưa đưa nó lên. Dù sao, tôi không muốn lan truyền nó ngay bây giờ, vì bài viết tôi đang viết sẽ thực sự giải thích các phần quan trọng tốt hơn nhiều và tập trung vào cách thực hiện nó, và nó sẽ được hoàn thành rất sớm.
Detheroc

@Detheroc Vui lòng thông báo tại đây và trên gamedev Q khi bạn hoàn thành bài viết. Giải thích vẫn chưa rõ ràng 100% cho tôi. Tôi sẽ đề nghị hiển thị các thành phần từng bước trong hình ảnh.
Kỹ sư

1
rất thích có thể sao chép kết quả hiện tại của bạn ngay cả khi chúng không tốt như kết quả trong tương lai của bạn, +1 để chia sẻ bất kỳ chi tiết nào bạn có thể. rất thú vị. Bạn đã xem xét ứng dụng của kỹ thuật đối với diễu hành tia (theo dõi hình cầu) chưa? Trong kết cấu khối lượng hoặc tương tự ...
Alan Wolfe

4
Luận án được công khai tại đây: dspace.cvut.cz/bitstream/handle/10467/62770/ Kẻ
Romain Guy

43

Xin lỗi về sự chờ đợi lâu, nhưng nó đã trở nên rõ ràng rằng mặc dù bài viết mà tôi đã hứa về cơ bản đã hoàn tất, quá trình xuất bản sẽ mất một thời gian. Do đó, thay vào đó, tôi đã chuẩn bị một chương trình nguồn mở với thuật toán xây dựng trường khoảng cách đa kênh mới, msdfgen , mà bạn có thể thử ngay bây giờ.

Nó có sẵn trên GitHub: https://github.com/Chlumsky/msdfgen

(Tôi chưa quen với điều này, vì vậy vui lòng cho tôi biết nếu có bất cứ điều gì sai với kho lưu trữ.)

Ai đó cũng hỏi về cách so sánh với trường khoảng cách đơn sắc lớn hơn, vì vậy đây là một lời trêu ghẹo về sự khác biệt về chất lượng. Tuy nhiên, nó thực sự phụ thuộc vào phông chữ cụ thể và tôi sẽ không nói rằng nó luôn có giá trị dữ liệu bổ sung.

Trường khoảng cách đa kênh 16x16 Trường khoảng cách đơn sắc 32x32


3

Khá thú vị! Tôi là tác giả của van ký giấy khoảng cách. Xin lỗi rằng đó là một chút thưa thớt về chi tiết thực hiện. Tôi chỉ đưa vào ví dụ hai kênh là công việc trong tương lai - Tôi không có máy phát điện. Tôi đã hình dung một cái gì đó như tạo ra một sdf độ phân giải cao và sau đó phân đoạn dựa trên góc độ của độ dốc của sdf sẽ là một chiến thuật hợp lý. Nhưng không bao giờ có được nó. Bất kỳ sơ đồ đa kênh nào cũng phải được cân nhắc với việc sử dụng dữ liệu kênh đơn có độ phân giải cao hơn có cùng dung lượng bộ nhớ, cho tỷ lệ phóng đại mà ứng dụng của bạn cần.


0

Tôi không có nghĩa là một chuyên gia về chủ đề này, nhưng về mặt lý thuyết, bạn có thể bảo toàn các góc nhọn trong một giả SDF đơn sắc nếu bạn sử dụng bộ lọc song phương một bộ lọc hai chiều thay vì bộ lọc song phương tiêu chuẩn. Bên cạnh lợi ích rõ ràng của việc tiết kiệm bộ nhớ, bạn cũng có thể có nhiều kênh cho đề can SDF nhiều màu.

Ngoài ra, nếu bạn không phiền khi sử dụng kênh thứ hai, thì bạn cũng có thể thử có một kênh cho Khoảng cách ngang và kênh khác cho Khoảng cách dọc và sử dụng Kim tự tháp năng lượng khác biệt của Laplacean (DoL) để nén kết cấu sao cho thông tin dư thừa sẽ không Sẽ được ghi lại.

Một giải pháp lý thuyết thứ ba và cuối cùng sẽ là thử nghiệm với Kết cấu được lấy mẫu lục giác thông qua Địa chỉ tập hợp mảng.

Thật không may, hiện tại tôi không có bất kỳ phương tiện nào để thử nghiệm ý tưởng của mình và không thể tìm thấy bất kỳ tài liệu nào mô tả hoặc thử nghiệm bất cứ điều gì tương tự với ý tưởng của tôi. Tôi sẽ liên kết tất cả các bài viết có liên quan nơi tôi có được thông tin / ý tưởng của mình trong thời gian ngắn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.