Le rendu des contours, à moins que le rendu d'une douzaine de caractères au total, reste un "no go" en raison du nombre de sommets par caractère approximatif de la courbure. Bien qu'il y ait eu des approches pour évaluer les courbes de bézier dans le pixel shader au lieu de cela, ces souffrent de n'être pas facilement lissé, ce qui est trivial à l'aide d'une distance-carte de texture quad, et l'évaluation des courbes dans le shader est encore computionally beaucoup plus cher que nécessaire.
Le meilleur compromis entre "rapide" et de la "qualité" sont toujours texturé quads signé à distance du champ de la texture. Il est très légèrement plus lent que d'utiliser une plaine normal texturé quad, mais pas tellement. La qualité d'autre part, est dans un tout autre ordre de grandeur. Les résultats sont vraiment magnifique, il est aussi rapide que vous pouvez obtenir, et des effets tels que la lueur sont trivialement facile à ajouter, trop. Aussi, la technique peut être déclassé bien pour du matériel plus ancien, si nécessaire.
Voir le célèbre Valve de papier pour la technique.
La technique est conceptuellement similaire à la façon dont surfaces implicites (metaballs et par exemple), même si elle ne génère pas de polygones. Il fonctionne entièrement dans le pixel shader et prend de la distance échantillonnés à partir de la texture en fonction de distance. Tout au-dessus d'un seuil choisi (généralement 0,5) est "in", tout le reste est "out". Dans le cas le plus simple, sur 10 ans non-shader-capable de matériel, réglage de l'alpha test de seuil à 0,5 va faire exactement la même chose (mais sans les effets spéciaux et l'antialiasing).
Si on veut ajouter un peu plus de poids à la police (faux gras), un peu moins de seuil fera l'affaire sans modifier une seule ligne de code (il suffit de changer votre "font_weight" uniforme). Pour un effet de brillance, tout simplement, on les considère au-dessus d'un seuil "dans" et tout au-dessus de l'autre (la plus petite), seuil ", mais en éclat", et de LERPs entre les deux. L'anticrénelage fonctionne de la même façon.
À l'aide d'un 8-bit signé de la valeur de distance plutôt que d'un seul bit, cette technique augmente la résolution efficace de votre texture de 16 fois dans chaque dimension (au lieu du noir et blanc, toutes les nuances sont utilisés, nous avons donc 256 fois les informations en utilisant le même stockage). Mais même si vous agrandissez bien au-delà de 16x, le résultat semble tout à fait acceptable. Les longues lignes droites finira par devenir un peu ondulée, mais il n'y aura pas de profil type "polyédrique" les artefacts de prélèvement.
Vous pouvez utiliser un geometry shader pour générer les quads de points (réduire la bande passante du bus), mais honnêtement, les gains sont plutôt marginales. Le même est vrai pour instanciées caractère de rendu comme décrit dans GPG8. La surcharge de l'instanciation n'est amorti si vous avez beaucoup de texte à dessiner. Les gains sont, à mon avis, en aucun rapport avec la complexité et la non-downgradeability. De Plus, vous êtes limité par le montant de la constante de registres, ou vous devez lire à partir d'une texture de la mémoire tampon de l'objet, qui n'est pas optimale pour la cohérence de cache (et le but était d'optimiser, pour commencer!).
Un simple, un bon vieux vertex buffer est tout aussi rapide (peut-être plus rapidement) si vous planifiez le téléchargement un peu en avance dans le temps et qui va s'exécuter sur tous les matériels construits au cours des 15 dernières années. Et, il n'est pas limité à un nombre de caractères dans la police, ni à un nombre de caractères à afficher.
Si vous êtes sûr que vous n'avez pas plus de 256 caractères dans votre police, de la texture des tableaux peut être la peine d'un examen à la bande la bande passante du bus dans une manière semblable à la génération des quads à partir de points dans le geometry shader. Lors de l'utilisation d'un tableau de texture, les coordonnées de texture de tous les quads sont identiques, constant s
et t
coordonnées et ne diffèrent que dans l' r
coordonner, ce qui est égal au caractère d'indice de rendu.
Mais comme avec les autres techniques, les gains attendus sont marginale et le coût d'être incompatible avec la précédente génération de matériel.
Il est un outil pratique par Jonathan Dummer pour la génération de distance de textures: la page de description
Mise à jour:
Comme l'a récemment souligné dans Programmables Sommet de Traction (D. Rákos, "OpenGL Insights", pp. 239) n'est pas significative latence supplémentaire ou des frais généraux associés à la traction sommet de données par programmation à partir de l'ombrage sur les dernières générations de Gpu, par rapport à faire de même en utilisant le standard de fonction fixe.
Aussi, les dernières générations de Processeurs de plus en plus, de taille raisonnable, à des fins générales caches L2 (par exemple 1536kiB sur nvidia Kepler), donc on peut s'attendre de la incohérente problème d'accès lors de l'extraction aléatoire de compensations pour le quad coins à partir d'un tampon texture être moins un problème.
Cela rend l'idée de traction constante des données (telles que quad tailles) à partir d'un tampon texture plus attrayant. Une hypothétique mise en œuvre pourrait, ainsi, de réduire PCIe et la mémoire des transferts, ainsi que la mémoire GPU, au minimum avec une approche comme ceci:
- Seulement de téléchargement d'un caractère d'index (un par personnage à être affiché) comme la seule entrée d'un vertex shader qui passe sur cet indice et
gl_VertexID
, et d'amplifier que de 4 points dans le géométrie shader, de toujours avoir le caractère d'index et que le sommet de l'id (ce sera "gl_primitiveID mis à disposition dans le vertex shader") comme le seul attributs, et la capture via la transformation de la rétroaction.
- Ce sera rapide, car il ya seulement deux attributs de sortie (principal goulot d'étranglement en GS), et il est proche de "non-op", sinon dans les deux étapes.
- Lier un tampon texture qui contient, pour chaque caractère dans la police, la texture de la quad positions des sommets par rapport au point de base (ce sont essentiellement les "mesures de police"). Ces données peuvent être compressées à 4 numéros par quad en ne stockant que le décalage de la partie inférieure gauche du vertex, et de codage de la largeur et de la hauteur de l'axe aligné boîte (en supposant que la moitié des flotteurs, ce sera de 8 octets de constante tampon par caractère, typique des 256 caractères de la police pourrait s'insérer complètement dans 2kiB du cache L1).
- Définir un uniforme pour la ligne de base
- Lier un tampon de la texture avec des décalages horizontaux. Ces pourrait probablement même être calculé sur le GPU, mais il est beaucoup plus facile et plus efficace pour ce genre de chose sur le CPU, car il est strictement séquentielle et n'est pas du tout trivial (crénage). Aussi, il aurait besoin d'un autre feedback passer, ce qui serait un autre point de synchronisation.
- Rendu précédemment, les données générées à partir de la rétroaction de la mémoire tampon, le vertex shader tire le décalage horizontal du point de base et les décalages de l'angle des sommets de tampon d'objets (à l'aide de la primitive id et le caractère d'index). L'original ID sommet des sommets est maintenant notre "primitive ID" (rappelez-vous la GS tourné les sommets en quads).
Comme cela, on pourrait, idéalement, de réduire le sommet de la bande passante par 75% (après amortissement), mais il ne serait en mesure de rendre une seule ligne. Si on voulait être en mesure de rendre plusieurs lignes dans un appel, il faut ajouter la ligne de base de la mémoire tampon texture, plutôt que d'utiliser un uniforme (ce qui rend la bande passante des gains plus petits).
Toutefois, même en supposant une réduction de 75% - depuis le sommet de données à afficher "raisonnable" d'un montant de texte n'est qu'à quelque part autour de 50-100kiB (qui est pratiquement de zéro à un GPU ou un bus PCIe) -- j'ai toujours le doute que l'augmentation de la complexité et de perdre la compatibilité ascendante est vraiment la peine. La réduction à zéro par 75% est toujours nulle. J'ai certes pas essayé l'approche ci-dessus, et plus de recherche serait nécessaire pour en faire une véritable déclaration qualifiée. Mais encore, sauf si quelqu'un peut prouver que vraiment impressionnante différence de performances (utilisation "normale" d'un montant de texte, pas des milliards de caractères!), de mon point de vue reste que, pour le sommet de données, un simple, à la vieille vertex buffer est à juste titre assez bon pour être considéré comme faisant partie d'un "état de l'art solution". C'est simple, il fonctionne, et il fonctionne bien.
Ayant déjà référencé "OpenGL " Perspectives" ci-dessus, il vaut la peine de signaler également le chapitre "Forme 2D Rendu par la Distance des Champs" par Stefan Gustavson, ce qui explique la distance de terrain, le rendu dans le plus grand détail.