Comment faire OpenGL live text-rendering pour une interface graphique?

j'implémente une interface graphique construite sur OpenGL. J'en suis venu au problème que chaque interface graphique aura -- le rendu de texte. Je connais plusieurs méthodes de rendu de texte en OpenGL, cependant, je me demande laquelle serait la mieux adaptée pour une interface graphique.

en général, dans une interface graphique, nous avons deux types de texte -- statique et en direct. Statique est assez facile, nous pouvons rendre une TTF à une texture et l'oublier. C'est le texte" live " qui me dérange le plus -- imaginez une console, ou un live chat dans un jeu multi-joueurs.

j'ai pensé à plusieurs options:

  • pas de cas particulier -- render et charger une texture à chaque fois que le texte change, en gardant à l'esprit seulement de le rediriger quand le nouveau texte apparaît réellement, et en essayant de diviser le plus grand texte en petites parties (comme par ligne de chat). Cependant, cela nous laisserait toujours pendus dans des cas comme une ligne de score qui change tout le temps, ou un texte d'intro qui rend "par caractère" (machine à écrire style vu dans certains de sci-fi jeux)
  • quad-per character -- cela aussi semble une solution populaire, vous préparez une texture avec la table ASCII et rendre un caractère quad texturé. Cependant, j'ai de sérieux doutes sur l'efficacité d'une telle solution. Conseils comment faire que plus rapide serait également la bienvenue.
  • solutions hybrides -- cependant je n'ai aucune idée comment mettre en œuvre que proprement

le question donc est -- comment rendre le texte dans OpenGL efficacement?

si cela peut aider, je coderai en C++ STL/Boost-heavy et je viserai les cartes graphiques GForce 6 et suivantes.

37

7 réponses

EDIT2: Sean Barrett vient de sortir bitmap fonts for C/C++ 3D programmers .

EDIT: un autre code gem qui vaut le coup d'oeil est Font Stash qui tire parti du stb_truetype de Sean Barrett.h .


vous pouvez créer une texture dans laquelle vous rendrez tous les caractères de votre police. Ensuite, il suffit de dessiner des quads texturés avec projection orthographique et coordonnées de texture appropriées: cette approche fonctionne lorsque votre texte est dans une langue qui ne contient pas beaucoup de symboles: comme l'anglais. La texture de la police est créée une fois au début de l'application et le rendu des quads est vraiment rapide.

C'est ce que j'utilise et je crois que c'est le moyen le plus rapide de rendre du texte en OpenGL. Au début, j'ai utilisé générateur de police Bitmap D'Angelcode outil et puis j'ai intégré FreeType directement et construit une grande texture contenant tous les glyphes au lancement de l'application. En ce qui concerne les conseils pour améliorer la vitesse de rendu des quads, je viens d'utiliser VBO comme pour le reste de la géométrie dans mon application.

je suis surpris que vous ayez des doutes sur le rendu du quad alors que vous ne semblez pas vous soucier de la performance de générer une texture sur le cpu, puis de la télécharger, puis de la lier pour finalement rendre un rectangle avec elle, cela pour chaque image. Changer les États D'OpenGL est le goulot d'étranglement, pas les 500 000 quads que vous utiliserez pour le texte.

aussi, regardez les bibliothèques comme la bibliothèque FTGL qui convertit la police entière en polygones (polices géométriques).

29
répondu Gregory Pakosz 2012-01-23 19:56:35

essayez de lire ceci: http://dmedia.dprogramming.com/?n=Tutorials.TextRendering1 .

L'approche décrite est la méthode habituelle pour un rendu de texte avec des Api graphiques. Un caractère par quadrilatère, et toutes les données d'image pour le texte dans une texture simple. Si vous pouvez ajuster tout votre jeu de caractères dans une texture (en fait, selon la taille de la texture, vous pourriez être en mesure d'adapter plusieurs) le rendu est extrêmement rapide.

la clé est que la liaison de texture est l'opération que vous devez minimiser. Si vous pouvez rendre tout votre texte avec une seule texture, peu importe la quantité de texte que vous devez mettre à l'écran. Même si vous devez changer les textures une poignée de fois (différentes polices, différents attributs de police [gras, soulignement, etc]) la performance devrait toujours être bonne. La performance du texte peut être plus critique pour un HUD, mais elle est moins importante dans l'interface graphique.

8
répondu luke 2010-01-15 13:47:12

vous pouvez rendre le texte comme des faces triangulées, et éviter d'utiliser une texture. De cette façon, vous évitez les contours flous lorsque le texte est zoomé. J'ai écrit une police poly ASCII basse qui est open sourced et disponible à my github .

une autre façon d'avoir des arêtes vives sur votre texte est SDF fonte , mais cela souffre de certains artefacts.

4
répondu Bram 2015-03-07 03:53:11

pourrait simplement utiliser ces deux fonctions:

void renderstring2d(char string[], float r, float g, float b, float x, float y)
{
    glColor3f(r, g, b);

    glRasterPos2f(x, y);
    for(unsigned int i = 0; i &lt strlen(string); i++)
        glutBitmapCharacter(GLUT_BITMAP_9_BY_15, string[i]);
}

void renderstring3d(char string[], float r, float g, float b, float x, float y, float z)
{
    glDisable(GL_LIGHTING);
    glColor3f(r, g, b);

    glRasterPos3f(x, y, z);
    for(unsigned int i = 0; i &lt strlen(string); i++)
        glutBitmapCharacter(GLUT_BITMAP_9_BY_15, string[i]);
}

ensuite, lorsque vous créez du texte 2D, n'oubliez pas de réinitialiser les matrices modelview et projection.

glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();

// Render text and quads

glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();

vous n'avez pas besoin de rendre à un quad en utilisant ces fonctions, parce que ces fonctions rendent directement au framebuffer.

et si ça ne marche pas pour vous, regardez ça. http://www.opengl.org/resources/faq/technical/fonts.htm

il parle de rendre le texte en utilisant glBitmap, glDrawPixels, et alpha blending.

1
répondu Ned Bingham 2010-01-15 14:45:29

c'est délicat à faire, surtout si vous voulez utiliser des techniques de rendu de police subpixel. Regardez le ClanLib SDK . Il utilise un rendu par lots pour afficher un écran complet de texte dans un seul appel OpenGL. Puisqu'il a une licence basée sur zlib, vous pouvez extraire son code si vous ne souhaitez pas utiliser le SDK lui-même

1
répondu rombust 2013-09-25 09:49:47

par caractère de quad manipulé pensait qu'une liste d'affichage (mise à jour seulement lorsque le texte change) est tout à fait suffisante pour la plupart des cas.

Je l'ai utilisé avec les polices X11 en utilisant XLoadQueryFont, glGenLists, glXUseXFont, glCallLists vous avez un tableau de listes d'affichage décrivant chaque caractère.

la fonction glCallLists accepte un argument char * pour votre texte et il peut être intégré dans une liste d'affichage.

donc vous finissez avec un un seul appel pour afficher le texte des blocs.

la texture de police suggérée par G. Pakosz est similaire, mais vous calculez vos propres listes d'affichage" by character".

vos premières options seront plus lentes car elles nécessiteront un rendu basé sur le processeur à chaque changement de texte.

0
répondu fa. 2010-01-15 13:48:46