Théorie
Pourquoi c'est difficile
Les formats de polices les plus courants, tels que TrueType y OpenType sont des formats vectoriels : ils utilisent Courbes de Bézier pour définir la limite de la lettre.
Source de l'image .
Transformer ces formats en tableaux de pixels (rastérisation) est trop spécifique et hors de portée d'OpenGL, notamment parce qu'OpenGl n'a pas de primitives non droites (voir par exemple Pourquoi n'y a-t-il pas de cercle ou d'ellipse primitif dans OpenGL ? )
L'approche la plus simple est de commencer par tramer les polices nous-mêmes sur le processeur, puis de donner le tableau de pixels à OpenGL en tant que texture.
OpenGL sait donc très bien gérer les tableaux de pixels à travers les textures.
Atlas des textures
Nous pourrions tramer les personnages pour chaque image et recréer les textures, mais ce n'est pas très efficace, surtout si les personnages ont une taille fixe.
L'approche la plus efficace consiste à tramer tous les personnages que vous prévoyez d'utiliser et à les regrouper sur une seule texture.
Ensuite, on transfère le tout au GPU une fois, et on utilise la texture avec des coordonnées uv personnalisées pour choisir le bon personnage.
Cette approche est appelée atlas des textures et il peut être utilisé non seulement pour les textures, mais aussi pour d'autres textures utilisées de manière répétée, comme les tuiles d'un jeu en 2D ou les icônes d'une interface web.
L'image Wikipédia de la texture complète, qui est elle-même tirée de freetype-gl, l'illustre bien :
Je soupçonne que l'optimisation du placement des personnages pour obtenir la plus petite texture possible est un problème NP-hard, voir : Quel algorithme permet de placer des rectangles de différentes tailles dans le plus petit rectangle possible de manière relativement optimale ?
La même technique est utilisée dans le développement web pour transmettre plusieurs petites images (comme des icônes) en une seule fois, mais elle est appelée "CSS Sprites" : https://css-tricks.com/css-sprites/ et sont utilisés pour masquer la latence du réseau plutôt que celle de la communication entre le CPU et le GPU.
Méthodes raster non-CPU
Il existe également des méthodes qui n'utilisent pas la trame de l'unité centrale pour les textures.
Le tramage par CPU est simple car il utilise le GPU le moins possible, mais nous commençons à nous demander s'il serait possible d'utiliser davantage l'efficacité du GPU.
Cette vidéo du FOSDEM 2014 explique les autres techniques existantes :
- tesselation : convertir la police en petits triangles. Le GPU est alors très doué pour dessiner des triangles. Inconvénients :
- génère un ensemble de triangles
- Calcul des triangles par l'unité centrale O(n log n)
- calculer des courbes sur les ombres. Un article publié en 2005 par Blinn-Loop a mis cette méthode sur le devant de la scène. Inconvénient : elle est complexe. Voir : Dessin de bézier cubique indépendant de la résolution sur GPU (Blinn/Loop)
- les implémentations matérielles directes telles que OpenVG . Inconvénient : la mise en œuvre n'est pas très répandue pour une raison quelconque. Voir aussi
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 la perspective (par rapport à un HUD orthogonal) est beaucoup plus compliqué, parce que la perspective peut rendre une partie du personnage beaucoup plus proche de l'écran et plus grande que l'autre, ce qui fait qu'une discrétisation uniforme du CPU (par exemple, raster, tesselation) semble mauvaise sur la partie la plus proche. Il s'agit d'un sujet de recherche actif :
Champs de distance sont l'une des techniques les plus répandues aujourd'hui.
Mise en œuvre
Les exemples qui suivent ont tous été testés sur Ubuntu 15.10.
Comme il s'agit d'un problème complexe, la plupart des exemples sont volumineux et dépasseraient la limite de 30 000 caractères de cette réponse, il suffit donc de cloner les dépôts Git respectifs pour compiler.
Cependant, ils sont tous entièrement open source, vous pouvez donc vous contenter de RTFS.
Solutions FreeType
FreeType semble être la bibliothèque de tramage de polices open source dominante, ce qui nous permettrait d'utiliser des polices TrueType et OpenType, ce qui en fait la solution la plus élégante.
Exemples / tutoriels :
Autres rastériseurs de polices
Ceux-ci semblent moins bons que FreeType, mais peuvent être plus légers :
Anton's OpenGL 4 Tutorials exemple 26 "Polices bitmap"
La police de caractères a été créée manuellement par l'auteur et stockée dans un fichier unique. .png
dossier. 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 rencontrerez des difficultés avec l'internationalisation.
Construire avec :
make -f Makefile.linux64
Aperçu de la sortie :
opengl-tutorial chapitre 11 "Polices 2D"
Les textures sont générées à partir de Fichiers DDS .
Le tutoriel explique comment les fichiers DDS ont été créés, à l'aide de CBFG y Paint.Net .
Aperçu de la sortie :
Pour une raison quelconque, Suzanne n'apparaît pas dans mon cas, mais le compteur de temps fonctionne correctement : https://github.com/opengl-tutorials/ogl/issues/15
FreeGLUT
GLUT a glutStrokeCharacter
et FreeGLUT est un logiciel libre... https://github.com/dcnieho/FreeGLUT/blob/FG_3_0_0/src/fg_font.c#L255
OpenGLText
https://github.com/tlorach/OpenGLText
TrueType raster. Par un employé de NVIDIA. Vise la réutilisation. Je ne l'ai pas encore essayé.
Exemple de SDK ARM Mali GLES
http://malideveloper.arm.com/resources/sample-code/simple-text-rendering/ semble encoder tous les caractères sur un PNG, et les couper à partir de là.
SDL_ttf
Fuente: https://github.com/cirosantilli/cpp-cheat/blob/d36527fe4977bb9ef4b885b1ec92bd0cd3444a98/sdl/ttf.c
Il vit dans une arborescence distincte de celle de SDL et s'intègre facilement.
Cependant, il ne fournit pas d'atlas de texture, ce qui limite les performances : Comment rendre efficacement les polices et le texte avec SDL2 ?
Filets apparentés