Je n'ai pas la possibilité d'utiliser mais les méthodes OpenGL (c'est-à-dire les méthodes glxxx()
). J'ai besoin de dessiner du texte en utilisant uniquement les méthodes gl. Après avoir lu le livre rouge, je comprends que cela n'est possible que par la méthode glBitmap()
. Si c'est le seul moyen possible, alors quelqu'un peut-il m'aider avec les informations du tableau de pixels pour tous les personnages. Existe-t-il une autre façon de dessiner du texte?
Pourquoi c'est difficile
Les formats de police populaires comme TrueType et OpenType sont des formats vectoriels: ils utilisent courbes de Bézier pour définir la limite de la lettre.
La transformation de ces formats en tableaux de pixels (rastérisation) est trop spécifique et hors de portée d'OpenGL, spécialement parce que OpenGl n'a pas de primitives non droites (par exemple, voir Pourquoi n'y a-t-il pas de primitive de cercle ou d'ellipse dans OpenGL? )
L'approche la plus simple consiste à commencer par raster les polices nous-mêmes sur le processeur, puis à donner le tableau de pixels à OpenGL sous forme de texture.
OpenGL sait alors très bien gérer les tableaux de pixels à travers les textures.
Atlas de textures
Nous pourrions raster des caractères pour chaque image et recréer les textures, mais ce n'est pas très efficace, surtout si les caractères ont une taille fixe.
L'approche la plus efficace consiste à tramer tous les personnages que vous prévoyez d'utiliser et à les entasser sur une seule texture.
Ensuite, transférez cela au GPU une fois et utilisez-le texture avec des coordonnées uv personnalisées pour choisir le bon caractère.
Cette approche est appelée atlas de texture et elle peut être utilisée non seulement pour les textures, mais aussi pour d'autres textures utilisées à plusieurs reprises, comme les tuiles dans un jeu 2D ou les icônes de l'interface utilisateur Web.
L'image Wikipedia de la texture complète, elle-même tirée de freetype-gl, illustre bien cela:
Je soupçonne que l'optimisation du placement des caractères pour le plus petit problème de texture est un problème NP-difficile, voir: Quel algorithme peut être utilisé pour emballer des rectangles de différentes tailles dans le plus petit rectangle possible d'une manière assez optimale?
La même technique est utilisée dans le développement Web pour transmettre plusieurs petites images (comme des icônes) à la fois, mais là on l'appelle "CSS Sprites": https://css-tricks.com/css-sprites/ = et sont utilisés pour masquer la latence du réseau au lieu de celle de la communication CPU/GPU.
Méthodes raster non-CPU
Il existe également des méthodes qui n'utilisent pas le raster CPU pour les textures.
Le rastering du processeur est simple car il utilise le moins possible le GPU, mais nous commençons également à penser s'il serait possible d'utiliser davantage l'efficacité du GPU.
Cette vidéo FOSDEM 2014 explique d'autres techniques existantes:
Polices à l'intérieur de la géométrie 3D avec perspective
Le rendu des polices à l'intérieur de la géométrie 3D avec perspective (par rapport à un HUD orthogonal) est beaucoup plus compliqué, car la perspective pourrait rendre une partie du personnage beaucoup plus proche de l'écran et plus grande que l'autre, créant ainsi une discrétisation uniforme du processeur (par exemple raster, tesselation) semblent mauvais sur la partie proche. Il s'agit en fait d'un sujet de recherche actif:
Champs de distance sont maintenant l'une des techniques les plus utilisées.
Les exemples qui suivent ont tous été testés sur Ubuntu 15.10.
Parce que c'est un problème complexe comme discuté précédemment, la plupart des exemples sont grands et feraient exploser la limite de 30k caractères de cette réponse, il suffit donc de cloner les référentiels Git respectifs à compiler.
Cependant, ils sont tous entièrement open source, vous pouvez donc simplement RTFS.
Solutions FreeType
FreeType ressemble à la bibliothèque de rastérisation de polices open source dominante, elle nous permettrait donc d'utiliser les polices TrueType et OpenType, ce qui en fait la solution la plus élégante.
https://github.com/rougier/freetype-gl
Était un ensemble d'exemples OpenGL et freetype, mais évolue plus ou moins dans une bibliothèque qui le fait et expose une API décente.
Dans tous les cas, il devrait déjà être possible de l'intégrer dans votre projet en copiant-collant du code source.
Il fournit à la fois un atlas de texture et des techniques de champ de distance hors de la boîte.
Démos sous: https://github.com/rougier/freetype-gl/tree/master/demos
N'a pas de paquet Debian, et il est difficile de compiler sur Ubuntu 15.10: https://github.com/rougier/freetype-gl/issues/82#issuecomment-216025527 (problèmes d'empaquetage, certains en amont), mais cela s'est amélioré à partir de 16h10.
N'a pas de méthode d'installation Nice: https://github.com/rougier/freetype-gl/issues/115
Génère de belles sorties comme cette démo:
libdgx https://github.com/libgdx/libgdx/tree/1.9.2/extensions/gdx-freetype
Exemples/tutoriels:
Autres tramages de polices
Ceux-ci semblent moins bons que FreeType, mais peuvent être plus légers:
Tutoriels OpenGL 4 d'Anton, exemple 26 "Polices Bitmap"
La police a été créée manuellement par l'auteur et stockée dans un seul .png
fichier. Les lettres sont stockées sous forme de tableau à l'intérieur de l'image.
Cette méthode n'est bien sûr pas très générale et vous auriez des difficultés avec l'internationalisation.
Construisez avec:
make -f Makefile.linux64
Aperçu de sortie:
Opengl-Tutorial Chapter 11 "Polices 2D"
Les textures sont générées à partir de fichiers DDS .
Le didacticiel explique comment les fichiers DDS ont été créés, à l'aide de CBFG et Paint.Net .
Aperçu de sortie:
Pour une raison quelconque, Suzanne manque pour moi, mais le compteur de temps fonctionne bien: https://github.com/opengl-tutorials/ogl/issues/15
FreeGLUT
GLUT a glutStrokeCharacter
et FreeGLUT est open source ... https://github.com/dcnieho/FreeGLUT/blob/FG_3_0_0/src/fg_font.c#L255
OpenGLText
https://github.com/tlorach/OpenGLText
Trame TrueType. Par un employé de NVIDIA. Vise à être réutilisable. Je ne l'ai pas encore essayé.
Exemple de SDK ARM Mali GLES
http://malideveloper.arm.com/resources/sample-code/simple-text-rendering/ semble coder tous les caractères sur un PNG et les couper à partir de là.
SDL_ttf
Source: https://github.com/cirosantilli/cpp-cheat/blob/d36527fe4977bb9ef4b885b1ec92bd0cd3444a98/sdl/ttf.c
Vit dans une arborescence distincte de SDL et s'intègre facilement.
Cependant, ne fournit pas d'implémentation d'atlas de texture, donc les performances seront limitées: Comment rendre efficacement les polices et le texte avec SDL2?
Sujets associés
Dessiner du texte en clair OpenGL n'est pas une tâche directe. Vous devriez probablement jeter un œil aux bibliothèques pour ce faire (soit en utilisant une bibliothèque soit comme exemple d'implémentation).
Certains bons points de départ pourraient être GLFont , OpenGL Font Survey et NeHe Tutorial for Bitmap Fonts (Windows) .
Notez que les bitmaps ne sont pas le seul moyen d'obtenir du texte dans OpenGL comme mentionné dans l'enquête sur les polices.
Utilisez glutStrokeCharacter(GLUT_STROKE_ROMAN, myCharString)
.
Un exemple: UN DÉMARREUR STAR WARS.
#include <windows.h>
#include <string.h>
#include <GL\glut.h>
#include <iostream.h>
#include <fstream.h>
GLfloat UpwardsScrollVelocity = -10.0;
float view=20.0;
char quote[6][80];
int numberOfQuotes=0,i;
//*********************************************
//* glutIdleFunc(timeTick); *
//*********************************************
void timeTick(void)
{
if (UpwardsScrollVelocity< -600)
view-=0.000011;
if(view < 0) {view=20; UpwardsScrollVelocity = -10.0;}
// exit(0);
UpwardsScrollVelocity -= 0.015;
glutPostRedisplay();
}
//*********************************************
//* printToConsoleWindow() *
//*********************************************
void printToConsoleWindow()
{
int l,lenghOfQuote, i;
for( l=0;l<numberOfQuotes;l++)
{
lenghOfQuote = (int)strlen(quote[l]);
for (i = 0; i < lenghOfQuote; i++)
{
//cout<<quote[l][i];
}
//out<<endl;
}
}
//*********************************************
//* RenderToDisplay() *
//*********************************************
void RenderToDisplay()
{
int l,lenghOfQuote, i;
glTranslatef(0.0, -100, UpwardsScrollVelocity);
glRotatef(-20, 1.0, 0.0, 0.0);
glScalef(0.1, 0.1, 0.1);
for( l=0;l<numberOfQuotes;l++)
{
lenghOfQuote = (int)strlen(quote[l]);
glPushMatrix();
glTranslatef(-(lenghOfQuote*37), -(l*200), 0.0);
for (i = 0; i < lenghOfQuote; i++)
{
glColor3f((UpwardsScrollVelocity/10)+300+(l*10),(UpwardsScrollVelocity/10)+300+(l*10),0.0);
glutStrokeCharacter(GLUT_STROKE_ROMAN, quote[l][i]);
}
glPopMatrix();
}
}
//*********************************************
//* glutDisplayFunc(myDisplayFunction); *
//*********************************************
void myDisplayFunction(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0, 30.0, 100.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
RenderToDisplay();
glutSwapBuffers();
}
//*********************************************
//* glutReshapeFunc(reshape); *
//*********************************************
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, 1.0, 1.0, 3200);
glMatrixMode(GL_MODELVIEW);
}
//*********************************************
//* int main() *
//*********************************************
int main()
{
strcpy(quote[0],"Luke, I am your father!.");
strcpy(quote[1],"Obi-Wan has taught you well. ");
strcpy(quote[2],"The force is strong with this one. ");
strcpy(quote[3],"Alert all commands. Calculate every possible destination along their last known trajectory. ");
strcpy(quote[4],"The force is with you, young Skywalker, but you are not a Jedi yet.");
numberOfQuotes=5;
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 400);
glutCreateWindow("StarWars scroller");
glClearColor(0.0, 0.0, 0.0, 1.0);
glLineWidth(3);
glutDisplayFunc(myDisplayFunction);
glutReshapeFunc(reshape);
glutIdleFunc(timeTick);
glutMainLoop();
return 0;
}
Cet article décrit comment rendre du texte dans OpenGL en utilisant diverses techniques.
En utilisant uniquement opengl, il existe plusieurs façons:
Chargez une image avec des caractères comme texture et dessinez la partie de cette texture en fonction du caractère que vous souhaitez. Vous pouvez créer cette texture à l'aide d'un programme Paint, la coder en dur ou utiliser un composant de fenêtre pour dessiner sur une image et récupérer cette image pour une copie exacte des polices système.
Pas besoin d'utiliser Glut ou toute autre extension, juste l'opérabilité OpenGL de base. Il fait le travail, sans oublier que cela a été fait comme ça pendant des décennies par des programmeurs professionnels dans des jeux très réussis et d'autres applications.
Je pense que la meilleure solution pour dessiner du texte en OpenGL est les polices de texture, je travaille avec elles depuis longtemps. Ils sont flexibles, rapides et agréables (à quelques exceptions près). J'utilise un programme spécial pour convertir des fichiers de polices (.ttf par exemple) en texture, qui est enregistré dans un fichier de format "police" interne (j'ai développé un format et un programme basés sur http: //content.gpwiki .org/index.php/OpenGL: Tutoriels: Font_System bien que ma version soit assez loin de l'Unicode de support d'origine et ainsi de suite). Lors du démarrage de l'application principale, les polices sont chargées à partir de ce format "interne". Regardez le lien ci-dessus pour plus d'informations.
Avec une telle approche, l'application principale n'utilise pas de bibliothèques spéciales comme FreeType, ce qui n'est pas souhaitable pour moi également. Le texte est dessiné à l'aide des fonctions OpenGL standard.