Il s'agit d'une démonstration du texte de rendu directement sur le GPU à l'aide des contours vectoriels définis par la police.
Les contours d'un glyphe sont convertis en une liste de courbes de Bezier quadratiques individuelles (définies par leurs points de contrôle), qui sont téléchargées sur le GPU.
Un quad est généré pour chaque glyphe et le shader de pixel détermine si chaque pixel est à l'intérieur ou à l'extérieur du glyphe. Pour ce faire, le numéro d'enroulement du pixel est calculé en se croisant un rayon avec les courbes de Bezier. À chaque intersection, le rayon entre ou sort de la zone remplie telle que déterminée par la direction de la courbe de Bezier par rapport au rayon. À chaque sortie, le nombre d'enroulement est augmenté de un et à chaque entrée, le nombre d'enroulement est diminué d'une. Après avoir envisagé toutes les intersections, le numéro d'enroulement ne sera pas nul si le pixel est à l'intérieur du contour.
La direction des rayons n'a pas d'importance pour ce calcul de numéro d'enroulement, mais les mathématiques peuvent être considérablement simplifiées en utilisant les rayons parallèles à l'axe X. En soustrayant la position de l'échantillon des points de contrôle des courbes de Bezier, le système de coordonnées est décalé de sorte que l'origine du rayon soit à
Pour trouver les intersections entre un rayon et une seule courbe de Bezier, rappelez-vous qu'une courbe quadratique Bezier est décrite par la formule suivante (pour fond sur les courbes de Bezier, voir la beauté et l'amorce):
Ne prenant que le composant y et applique la condition
Qui peut être réorganisé en:
Afin qu'il puisse être résolu en utilisant la formule quadratique:
Substituant
L'équation quadratique peut avoir zéro, une ou deux solutions. De plus, une solution
À ce stade, les intersections entre le rayon et la courbe de Bezier ont été identifiées, mais elles doivent toujours être classées comme entrée ou sortie. La démo fournie par Dobbie calcule explicitement la dérivée de la courbe de Bezier pour chaque
Par conséquent, la courbe de Bezier traverse l'axe x dans une direction fixe à chaque solution et, combinée à la convention pour l'orientation du contour,
Une approche différente pour comprendre cette relation consiste à remarquer qu'en raison des différents signes utilisés dans les solutions et de la racine carrée n'est pas négative,
Si le paramètre
L'anti-aliasage le long de la direction des rayons est mis en œuvre en considérant une fenêtre de la taille d'un pixel autour de l'origine du rayon. Si une intersection tombe dans cette fenêtre, alors le numéro d'enroulement est modifié uniquement pour calculer la couverture du pixel. Le poids fractionnaire est déterminé par la distance entre le bord gauche du pixel (cela est cohérent avec les rayons pointant vers la droite). En considérant les sections individuelles, on peut voir que cela calcule exactement la couverture unidimensionnelle.
Notez que nous devons également considérer les intersections légèrement derrière l'origine du rayon maintenant, mais l'implémentation calcule d'abord toute intersection avec l'axe X, puis vérifie la position X, donc elle ne change pas beaucoup. Une autre façon de penser à ce sujet est que la condition
Pour un anti-aliasing complet, nous pouvons utiliser plusieurs rayons dans différentes directions (par exemple, le long de l'axe x et un le long de l'axe y).
Ce type de technique est soumis à des artefacts de la précision numérique limitée des nombres de points flottants. L'image ci-dessous montre une instance de tels artefacts lorsqu'il est complètement zoomé (et sachant où chercher). Néanmoins, j'ai déjà trouvé que cette implémentation était déjà assez stable numériquement. Tous les artefacts restants pourraient être éliminés à l'aide de l'algorithme Slug, qui n'est pas mis en œuvre ici en raison du brevet associé.
Cette démonstration n'implémente pas non plus d'optimisations de performances (comme les bandes) et pourrait avoir une utilisation élevée du GPU dans certains scénarios et lors de l'utilisation de polices très complexes.

Clone le projet récursivement pour initialiser les sous-modules pour les dépendances (ou exécuter git submodule update --init si vous avez déjà cloné le repo):
git clone --recursive https://github.com/GreenLightning/gpu-font-rendering.git
cd gpu-font-rendering
# Note: CMake will create the build directory.
cmake -S . -B build
make -j8 --directory build
Sur Windows, vous voudrez peut-être utiliser CMake GUI et / ou Visual Studio à la place.
Sur Linux, vous devrez peut-être installer des packages supplémentaires pour OpenGL Development (par exemple sudo apt-get install xorg-dev libgl1-mesa-dev pour ubuntu).
./build/main
Le programme exige que les répertoires fonts et shaders soient dans le répertoire actuel pour charger ses ressources. Si vous n'obtenez qu'une fenêtre noire , c'est probablement le problème. Vérifiez votre répertoire de travail et vérifiez les erreurs de la console.
Testé sur Windows 10, MacOS Monterey et Ubuntu 22.04.