Phác thảo phông chữ trong OpenGL, FTGL


8

Tôi đang sử dụng thư viện FTGL để kết xuất phông chữ trong trò chơi của mình, nhưng tôi hoàn toàn không biết làm thế nào để tạo một phác thảo xung quanh văn bản. Đạt được một cái bóng có thể dễ dàng, bởi vì tôi chỉ có thể làm điều đó như thế này:

(mã giả)

font.render(Color::BLACK, position.x + 1, position.y + 1); // Shadow
font.render(Color::WHITE, position.x, position.y)          // Normal text

Nhưng làm thế nào để tạo ra một phác thảo? Thật không may, tôi đã không tìm thấy bất kỳ giải pháp thú vị nào cho nó qua internet có vẻ hơi lạ, vì tôi nghĩ đó là vấn đề khá phổ biến.

Vẽ phác thảo chỉ với một phông chữ lớn hơn không phải là một cách đúng đắn, vì như tôi đã tìm ra, các chữ cái không khớp trong trường hợp này:

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

Vì vậy, có cách nào đơn giản để tạo ra một phác thảo cho phông chữ? Làm thế nào để họ làm điều đó trong các trò chơi thực sự?

Cảm ơn trước cho bất kỳ câu trả lời


1
Một giải pháp bẩn có thể là kết xuất thành một kết cấu cùng một văn bản, và sau đó kết xuất kết cấu này được tăng tỷ lệ x1.2, chẳng hạn.
Dan

2
@Dan Điều đó sẽ dẫn đến chính xác những gì anh ấy đã thể hiện trong hình ảnh của mình ở trên. Ngay cả việc hiển thị một chữ cái tại một thời điểm theo cách này cũng sẽ dẫn đến các vấn đề, vì các đường viền bên ngoài sẽ dày hơn các chữ cái bên trong (có thể không tồn tại).
Kỹ sư

1
Bạn đang sử dụng loại phông chữ nào? FTGL hỗ trợ phông chữ Outline ngoài hộp cho phông chữ Vector. Độ rộng đường OpenGL có thể được sử dụng để kiểm soát độ dày.
Paul-Jan

Câu trả lời:


7

Linh hoạt & chính xác: Bộ lọc

Sử dụng bộ lọc texel trên kết cấu ở phía CPU hoặc nếu bạn đang sử dụng OpenGL đường ống lập trình, trực tiếp trong trình đổ bóng mảnh.

Ý tưởng của bộ lọc chỉ đơn giản là bạn chạy qua một vòng lặp 2D để xử lý mọi texel. Nếu nó có màu trắng, thì bạn chạy qua một vòng 2D bên trong cho mỗi pixel xung quanh của nó trong một số bán kính và điều chỉnh cho phù hợp. Đây còn được gọi là bộ lọc hộp, mặc dù nếu bạn bao gồm kiểm tra bán kính, nó thực sự là một bộ lọc tròn - giúp tránh sự giả tạo trục-al.

Một cách nhanh hơn để làm điều này là tính toán trước tập hợp các độ lệch từ mỗi pixel trung tâm mà bạn kiểm tra; bằng cách này, bạn không cần chạy căn bậc hai cho mỗi pixel xung quanh một pixel nhất định. Nói cách khác, bạn muốn giữ độ phức tạp xuống `O (texWidth * texHeight) thay vì O (texWidth * texHeight * filterRadius * filterRadius), nói cách khác.

Dễ dàng: Nhiều kết xuất

Một cách khác để đạt được hiệu ứng sẽ không phải là chia tỷ lệ văn bản, mà thay vào đó là hiển thị đường viền màu đỏ của bạn ở mỗi tám hướng (hoặc nhiều hơn), mỗi hướng sẽ hơi lệch so với ban đầu theo hướng đó:

 \|/
--+--
 /|\

Bằng cách bù đắp từng phiên bản màu đỏ như thế này, bạn sẽ có được cạnh ngoài khá đồng đều xung quanh văn bản gốc của mình. Hãy nhớ rằng khi dịch chuyển theo đường chéo, bạn nên sử dụng cùng một cường độ vectơ như khi bạn dịch chuyển theo chiều ngang hoặc chiều dọc, thay vì chỉ đơn giản là bù đắp bởi cùng các giá trị x và y (dẫn đến độ dài cơ bản xấp xỉ 1,4 lần - trig cơ bản).

FYI

Loại hiệu ứng này được gọi là sự giãn nở, và đôi khi được thực hiện thông qua Minkowski Summation , đây là cách tiếp cận dựa trên vectơ (liên tục) đối với bộ lọc hộp dựa trên pixel (lượng tử hóa) mà tôi đã mô tả ở trên.


6

Tính năng này được triển khai trực tiếp trong FTGL nhưng nó chỉ có sẵn trong ExtrudeFontlớp. Bạn chỉ cần xác định một sự khởi đầu cho phông chữ:

font = new FTExtrudeFont(...);
font->FaceSize(80);
font->Depth(0);
font->Outset(0, 5);

Sau đó, bạn có thể sử dụng một màu khác nhau cho hai chế độ kết xuất:

glColor3f(1.0, 1.0, 1.0); /* White inside */
font->Render("Hello", FTPoint(), FTPoint(), FTGL::RENDER_FRONT);
glColor3f(1.0, 0.0, 0.0); /* Red outline */
font->Render("Hello", FTPoint(), FTPoint(), FTGL::RENDER_SIDE);

Đây là kết quả, với khử răng cưa được bật và tắt:

Hình ảnh kết quả


Cảm ơn Sam! Đó thực sự là những gì tôi muốn nghe - FTGL thực sự có một cái gì đó như thế này. Một lần nữa xin cảm ơn.
Piotr Chojnacki

2

Không liên quan đến FTGL nhưng có một bài viết tuyệt vời từ Valve về kết xuất glyph. Nó cung cấp kết xuất chất lượng cao với yêu cầu bộ nhớ nhỏ và các hiệu ứng như đường viền hoặc bóng có thể được thực hiện đơn giản.


2
Đáng cảnh báo cho OP rằng phương pháp này đòi hỏi sự hiểu biết về đường ống GPU có thể lập trình, tức là các shader.
Kỹ sư
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.