Garis besar font di OpenGL, FTGL

8

Saya menggunakan perpustakaan FTGL untuk merender font di game saya, tapi saya sama sekali tidak tahu cara membuat garis besar di sekitar teks. Mencapai bayangan bisa mudah, karena saya bisa melakukannya seperti ini:

(kode semu)

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

Tetapi bagaimana cara membuat garis besar? Sayangnya saya belum menemukan solusi yang menarik untuk itu melalui internet yang menurut saya agak aneh, karena saya pikir ini masalah yang cukup populer.

Menggambar garis hanya dengan font yang lebih besar bukan cara yang benar, karena seperti yang saya ketahui, huruf tidak cocok dalam kasus ini:

masukkan deskripsi gambar di sini

Jadi apakah ada cara sederhana untuk membuat garis besar font? Bagaimana mereka melakukannya di game nyata?

Terima kasih sebelumnya atas jawaban apa pun

Piotr Chojnacki
sumber
1
Solusi kotor dapat membuat ke tekstur teks yang sama, dan kemudian membuat tekstur ini ditingkatkan x1.2, misalnya.
Dan
2
@Dan Itu akan mengarah ke apa yang telah ditunjukkan pada gambar di atas Bahkan merender satu huruf pada satu waktu dengan cara ini, akan menimbulkan masalah, karena garis luar akan lebih tebal daripada yang dalam (yang mungkin tidak ada).
Insinyur
1
Jenis font apa yang Anda gunakan? FTGL mendukung font Garis besar di luar kotak untuk font vektor. Lebar garis OpenGL dapat digunakan untuk mengontrol ketebalan.
Paul-Jan

Jawaban:

7

Fleksibel & Akurat: Filter

Gunakan filter texel baik pada tekstur di sisi CPU, atau jika Anda menggunakan OpenGL pipeline yang dapat diprogram, langsung di shader fragmen.

Ide filter adalah Anda menjalankan melalui loop 2D untuk memproses setiap texel. Jika berwarna putih, maka Anda menjalankan loop 2D bagian dalam untuk masing-masing piksel di sekitarnya dalam beberapa radius, dan beradaptasi sesuai itu. Ini juga dikenal sebagai filter kotak, meskipun jika Anda menyertakan pemeriksaan radius, itu benar-benar filter melingkar - yang menghindari artefak sumbu-al.

Cara yang lebih cepat untuk melakukan ini adalah dengan menghitung ulang set offset dari setiap piksel pusat yang Anda periksa; dengan cara ini, Anda tidak perlu menjalankan akar kuadrat untuk setiap piksel yang mengelilingi piksel yang diberikan. Anda ingin menjaga kompleksitas ke `O (texWidth * texHeight) daripada O (texWidth * texHeight * filterRadius * filterRadius), dengan kata lain.

Mudah: Banyak render

Cara lain untuk mencapai efeknya adalah bukan dengan skala teks, tetapi sebaliknya membuat garis merah Anda di masing-masing dari delapan (atau lebih) arah, masing-masing sedikit mengimbangi dari aslinya ke arah itu:

 \|/
--+--
 /|\

Dengan mengimbangi setiap versi merah seperti ini, Anda akan mendapatkan tepi luar yang cukup seragam di sekitar teks asli Anda. Ingatlah bahwa ketika menggeser secara diagonal, Anda harus menggunakan besaran vektor yang sama seperti ketika Anda menggeser secara horizontal atau vertikal, alih-alih hanya mengimbangi dengan nilai x dan y yang sama (yang mengarah ke panjang dasar kira-kira 1,4x lebih jauh - pemicu dasar).

FYI

Efek semacam ini dikenal sebagai pelebaran, dan kadang-kadang dilakukan melalui Minkowski Summation , yang merupakan pendekatan berbasis vektor (berkelanjutan) untuk filter kotak berbasis pixel (quantised) yang saya jelaskan di atas.

Insinyur
sumber
6

Fitur ini diimplementasikan secara langsung dalam FTGL tetapi hanya tersedia di ExtrudeFontkelas. Anda cukup mendefinisikan awal untuk font:

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

Kemudian Anda dapat menggunakan warna yang berbeda untuk dua mode render:

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);

Inilah hasilnya, dengan antialiasing diaktifkan dan dinyalakan:

Gambar yang dihasilkan

sam hocevar
sumber
Terima kasih, Sam! Itu benar-benar yang ingin saya dengar - bahwa FTGL sebenarnya memiliki sesuatu seperti ini. Sekali lagi terima kasih.
Piotr Chojnacki
2

Tidak terkait dengan FTGL tetapi ada artikel bagus dari Valve tentang rendering mesin terbang. Ini memberikan rendering berkualitas tinggi dengan kebutuhan memori kecil, dan efek seperti garis besar atau bayangan dapat dengan mudah diimplementasikan.

Thvvyn
sumber
2
Layak memperingatkan OP bahwa pendekatan ini membutuhkan pemahaman tentang jalur pipa GPU yang dapat diprogram, yaitu shader.
Insinyur