Contour des polices dans OpenGL, FTGL

8

J'utilise la bibliothèque FTGL pour rendre les polices dans mon jeu, mais je ne sais absolument pas comment créer un contour autour du texte. Atteindre une ombre pourrait être facile, car je peux simplement le faire comme ceci:

(pseudo code)

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

Mais comment créer un contour? Malheureusement, je n'ai trouvé aucune solution intéressante sur Internet, ce qui m'a semblé un peu étrange, car je pensais que c'était un problème assez populaire.

Dessiner un contour avec juste une police plus grande n'est pas une bonne façon, car comme je l'ai découvert, les lettres ne correspondent tout simplement pas dans ce cas:

entrez la description de l'image ici

Existe-t-il un moyen simple de créer un contour pour les polices? Comment font-ils dans les vrais jeux?

Merci d'avance pour toute réponse

Piotr Chojnacki
la source
1
Une mauvaise solution pourrait être de rendre à une texture le même texte, puis de rendre cette texture à l'échelle x1,2, par exemple.
Dan
2
@Dan Cela conduira exactement à ce qu'il a montré dans son image ci-dessus. Même le rendu d'une lettre à la fois de cette manière entraînerait des problèmes, car les contours extérieurs seraient plus épais que ceux intérieurs (qui pourraient être inexistants).
Ingénieur
1
Quel type de police utilisez-vous? FTGL prend en charge les polices Outline prêtes à l'emploi pour les polices Vector. La largeur de ligne OpenGL peut être utilisée pour contrôler l'épaisseur.
Paul-Jan

Réponses:

7

Flexible et précis: filtres

Utilisez un filtre texel soit sur la texture côté CPU, soit si vous utilisez le pipeline programmable OpenGL, directement dans le fragment shader.

L'idée d'un filtre est simplement que vous exécutez une boucle 2D pour traiter chaque texel. S'il est blanc, vous exécutez une boucle 2D intérieure pour chacun de ses pixels environnants dans un certain rayon et vous vous adaptez en conséquence. Ceci est également connu comme un filtre de boîte, bien que si vous incluez la vérification du rayon, c'est vraiment un filtre circulaire - ce qui évite les artefacts axiaux.

Un moyen plus rapide de procéder consiste à précalculer l'ensemble des décalages de chaque pixel central que vous vérifiez; de cette façon, vous n'avez pas besoin d'exécuter une racine carrée pour chaque pixel entourant un pixel donné. Vous voulez limiter la complexité à `O (texWidth * texHeight) plutôt qu'à O (texWidth * texHeight * filterRadius * filterRadius), en d'autres termes.

Facile: plusieurs rendus

Une autre façon d'obtenir l'effet serait de ne pas mettre le texte à l'échelle, mais plutôt de rendre votre contour rouge dans chacune des huit (ou plus) directions, chacune légèrement décalée de l'original dans cette direction:

 \|/
--+--
 /|\

En compensant chacune des versions rouges comme celle-ci, vous obtiendrez un bord extérieur assez uniforme autour de votre texte d'origine. Gardez à l'esprit que lorsque vous déplacez en diagonale, vous devez utiliser la même amplitude vectorielle que lorsque vous déplacez horizontalement ou verticalement, plutôt que de simplement compenser par les mêmes valeurs x et y (ce qui conduit à une longueur approximative de 1,4 fois plus - trig de base).

FYI

Ce type d'effet est connu sous le nom de dilatation, et est parfois effectué via Minkowski Summation , qui est l'approche vectorielle (continue) du filtre de boîte à pixels (quantifié) que j'ai décrit ci-dessus.

Ingénieur
la source
6

Cette fonctionnalité est implémentée directement dans FTGL mais elle n'est disponible que dans la ExtrudeFontclasse. Vous définissez simplement un début pour la police:

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

Ensuite, vous pouvez utiliser une couleur différente pour les deux modes de rendu:

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

Voici le résultat, avec l'antialiasing activé / désactivé:

Image résultante

sam hocevar
la source
Merci Sam! C'est vraiment ce que je voulais entendre - que FTGL a en fait quelque chose comme ça. Encore merci.
Piotr Chojnacki
2

Pas lié à FTGL mais il y a un excellent article de Valve sur le rendu des glyphes. Il offre un rendu de haute qualité avec peu de mémoire et des effets tels que les contours ou les ombres peuvent être simplement implémentés.

Thelvyn
la source
2
Il convient d'avertir l'OP que cette approche nécessite une compréhension du pipeline GPU programmable, c'est-à-dire des shaders.
Ingénieur