Rendu de texte net sur GPU
(osor.io)- L’approche Multi-Channel SDF existante gardait des limites avec les traits fins, les grands atlas, la réduction/l’agrandissement et les déplacements fluides ; elle a donc été réimplémentée en rastérisation à l’exécution sur GPU
- Le nouveau pipeline n’envoie au GPU que les données de courbes de Bézier des glyphes actuellement visibles, les dessine dans un atlas à l’exécution, puis les échantillonne à l’écran
- Tant qu’un glyphe reste à l’écran, le cache de l’atlas est conservé et des échantillons sont accumulés pour améliorer la qualité : on démarre à 8 samples-per-pixel sur la première frame, puis on affine jusqu’à 512 samples au maximum
- La clé de cache inclut la font, le glyph_index, la taille en pixels et le décalage sous-pixel ; une virgule fixe sur 8 bits regroupe les positions et tailles proches sous une même valeur afin d’améliorer la réutilisation
- En modélisant la structure sous-pixel RGB propre à chaque écran comme une zone d’échantillonnage, on peut réduire les franges colorées même sur des agencements non standard comme l’OLED G9 ; une démo de texte en plein écran 4K montre un coût de pointe d’environ 0,1 ms sur Radeon 9070
Pourquoi choisir la rastérisation vectorielle à l’exécution plutôt que les SDF
- L’implémentation existante utilisait les Multi-Channel Signed Distance Fields et fonctionnait globalement bien, mais plusieurs limites subsistaient en usage réel
- Qualité : avec des traits fins ou des polices très détaillées, des caractéristiques disparaissaient ou des artefacts apparaissaient, et il fallait parfois des SDF de plus haute résolution
- Taille de l’atlas : les SDF étant générés hors ligne puis stockés dans un atlas, il est difficile de cuire dans un seul atlas des polices japonaises ou chinoises contenant de nombreux glyphes
- Flexibilité : il est délicat d’appliquer de nouvelles idées comme la réduction/l’agrandissement ou l’anticrénelage sous-pixel, et cela ne convenait pas non plus aux images vectorielles générables et modifiables à l’exécution
- Simplicité : l’étape qui convertit les courbes de glyphe d’origine en texture intermédiaire augmente la complexité du système
- Même une police latine comme Miama nécessitait un atlas
4096×1152avec une zone64×64par glyphe ; utiliser plusieurs polices à l’exécution augmente donc les coûts en mémoire et en bande passante de streaming - Le but de la nouvelle approche est d’utiliser plus directement les courbes de Bézier créées par le concepteur du glyphe, afin de réduire les étapes de transformation entre les données d’origine et les pixels finaux
Pipeline global
- L’idée centrale consiste à ne pas précuire tous les glyphes hors ligne, mais à envoyer au GPU uniquement les courbes des glyphes actuellement visibles et à les rastériser au moment où elles sont nécessaires
- Le flux de traitement est simple
- Charger les données de courbes de glyphes depuis la police
- Le GPU rastérise les glyphes dans un atlas à l’exécution
- Lors de l’affichage, cet atlas est échantillonné
- Si le même glyphe continue d’être utilisé dans les frames suivantes, il reste dans l’atlas et des échantillons sont accumulés pour affiner jusqu’à obtenir un anticrénelage sous-pixel de haute qualité
- Comme la représentation vectorielle est rendue directement, il est plus facile de s’adapter aux changements de résolution et de calculer non seulement la couverture d’un pixel entier, mais aussi celle de chaque élément sous-pixel
Traitement des courbes de glyphes
- Pour le chargement des polices, FreeType est utilisé comme couche intermédiaire dans un outil hors ligne afin de lire les formats pris en charge, parcourir les courbes de chaque glyphe et les enregistrer dans un format d’asset propre
- Les courbes de glyphe peuvent inclure des lignes, des Bézier quadratiques et des Bézier cubiques ; pour simplifier le shader, elles sont toutes converties en Bézier quadratiques
- Une ligne est transformée en Bézier quadratique en ajoutant un point de contrôle au milieu des deux points
- Une Bézier cubique est divisée en deux Bézier quadratiques, une conversion avec perte qui réduit le degré
- Diviser une Bézier cubique en deux Bézier quadratiques a bien fonctionné sur la plupart des polices testées, mais des méthodes plus sophistiquées permettant de réduire davantage l’erreur sont possibles
- Si une conversion de meilleure qualité est nécessaire, un outil hors ligne peut convertir la police dans un format ne contenant que des Bézier quadratiques, comme TrueType
.ttf, afin d’éviter cette conversion - Le graphe Desmos permet de comparer la forme de la Bézier cubique d’entrée et des deux Bézier quadratiques obtenues
Calcul de couverture et optimisation de l’accès aux courbes
- La couverture est calculée pixel par pixel en lançant un rayon horizontal de gauche à droite, en testant les intersections avec les courbes et en accumulant le winding number
- Pour le contexte mathématique et l’implémentation, on peut se référer à GPU Font Rendering de GreenLightning et à la vidéo Rendering Text de Sebastian Lague
- Les imprécisions de calcul d’intersection peuvent apparaître pour des échantillons à certaines hauteurs, mais après accumulation de centaines d’échantillons, une ou deux erreurs deviennent presque invisibles après moyennage
- Avec une accumulation maximale de 512 échantillons, si un échantillon est faux, on obtient
1/512=0.00195au lieu de0, ou511/512=0.99804au lieu de1 - On peut aussi fixer un seuil de clamp lorsque la couverture est proche des valeurs extrêmes
- Avec une accumulation maximale de 512 échantillons, si un échantillon est faux, on obtient
- La distribution des positions d’échantillonnage utilise la séquence $R_2$ de Martin Roberts, et l’exemple Shadertoy permet d’observer sa distribution dans le temps
- Pour réduire le coût d’accès aux courbes, le glyphe est découpé en plusieurs bandes horizontales, et seules les courbes touchant chaque bande sont stockées sous forme de bitset
- Comme seuls des rayons horizontaux sont suivis, l’ensemble de courbes que chaque texel doit tester peut être fortement réduit
- En faisant accéder un wave à la même plage de bandes, on peut scalariser l’itération sur les courbes et leurs lectures
- Dans le compute shader, lors de la rastérisation dans l’atlas, les threads sont packés horizontalement en row-major afin de minimiser la plage de bandes touchée par un wave
Packing de l’atlas et clé de cache
- Au départ, la rastérisation se faisait directement à l’écran, mais le coût de calcul d’un anticrénelage de haute qualité à chaque frame était élevé
- La plupart des textes restent à la même taille et à la même position pendant plusieurs frames, et les mêmes glyphes se répètent à la même taille ; un atlas avec accumulation temporelle est donc adapté
- Si un glyphe requis n’est pas présent, l’atlas lui alloue de l’espace et lance la rastérisation ; s’il est déjà présent, le résultat existant est utilisé tel quel
- Pendant une frame, les glyphes de l’atlas sont inspectés afin de décider s’il faut les conserver, les échantillonner davantage ou libérer l’espace s’ils ne sont plus utilisés
- La clé de l’atlas inclut les éléments suivants
fontglyph_indexquantized_size_in_pixels_x,quantized_size_in_pixels_yquantized_subpixel_offset_x,quantized_subpixel_offset_y
- Le décalage sous-pixel correspond à
frac(pixel_position)et est nécessaire pour produire un anticrénelage adapté à la position lorsque le glyphe n’est pas exactement aligné sur la grille de pixels ou lorsqu’il défile de manière fluide - Si les valeurs à virgule flottante étaient utilisées telles quelles comme clés, des valeurs mathématiquement identiques pourraient différer au niveau des bits ; les positions et tailles proches sont donc regroupées en valeurs identiques avec une virgule fixe dont la partie fractionnaire est sur 8 bits
- Dans un éditeur de texte contenant beaucoup de texte statique avec une police à chasse fixe, aligner l’espacement des caractères et la position des lignes sur les limites de pixels peut améliorer le taux de hit du cache d’atlas pour un même glyphe
Placement dans l’atlas basé sur le Z-Order
- Le placement des glyphes à l’exécution utilise le Z-Order Packing et un bitset de cellules libres
- Le Z-Order basé sur les codes de Morton permet de traiter des cellules 2D comme un long tableau 1D ; lorsqu’on alloue un nombre continu de cellules égal à une puissance de deux, on obtient une région carrée dans l’atlas 2D
- La cellule de base mesure
16×16texels, et la taille du glyphe est arrondie à la puissance de deux supérieure- Par exemple, un glyphe
25×29reçoit un chunk32×32 - Dans ce cas, quatre cellules
16×16sont nécessaires ; on cherche donc quatre bits consécutifs alignés et on les utilise
- Par exemple, un glyphe
- Les glyphes longs et fins de l’alphabet latin sont souvent verticaux ; avec un Z-Order transposé, des glyphes comme
l,j,iou1peuvent n’utiliser que la moitié de l’espace - À l’inverse, pour une écriture comme l’arabe, où les glyphes longs et fins sont horizontaux, le Z-Order standard est plus adapté
Améliorer la qualité par accumulation temporelle
- Tant qu’un glyphe reste dans l’atlas, il est possible d’ajouter quelques échantillons à chaque frame pour affiner le résultat
- Le planning de base démarre avec 8 samples-per-pixel lors de la première frame où le glyphe apparaît, puis ajoute 4 échantillons à la frame suivante, 2 à la suivante, puis 1 à chaque frame, jusqu’à un total de 512
- La première frame est volontairement de bonne qualité, car un glyphe qui se déplace de manière fluide ou change de taille est en pratique réinitialisé à chaque frame
- La qualité et les performances peuvent être ajustées de plusieurs façons
- Le nombre d’échantillons/rayons ajoutés à chaque frame
- L’augmentation éventuelle du nombre d’échantillons durant les premières frames d’un glyphe
- La limite supérieure du nombre total d’échantillons par frame
- Le time-slicing, qui met à jour les glyphes existants toutes les quelques frames plutôt qu’à chaque frame
- Une méthode limitant le coût des tests d’intersection selon le nombre de courbes du glyphe
- Dans cette implémentation, les performances n’ont pas posé de problème majeur : le texte en plein écran de l’introduction affichait un pic d’environ 0,1 ms en 4K sur Radeon 9070, et lorsque les glyphes atteignent le nombre maximal d’échantillons, le coût retombe rapidement vers 0
Anticrénelage sous-pixel et franges colorées
- L’anticrénelage sous-pixel rend les éléments rouge, vert et bleu à l’intérieur d’un pixel de l’écran comme autant de zones d’échantillonnage distinctes
- Avec la structure en bandes verticales d’un LCD RGB traditionnel, la résolution horizontale est en pratique triplée, ce qui permet de traiter du
3840×2160en 4K comme du3840×6480 - Le problème est que certains écrans, comme l’OLED G9, ont une structure sous-pixel non standard, différente des bandes verticales RGB classiques
- En supposant par défaut une structure en rectangles verticaux RGB, on voit des franges vertes en haut et magenta en bas
- En plaçant les positions d’échantillonnage selon la structure sous-pixel réelle de l’écran, les franges colorées disparaissent presque et le résultat est plus doux
- Subpixel Zoo présente divers exemples de structures sous-pixel, et la structure red-white-blue-green des LG WOLED est un exemple qui diffère de l’ordre standard
- Des résultats plus précis ont été obtenus en considérant les éléments sous-pixel comme plus grands que leur taille physique réelle et en les faisant se chevaucher
- La lumière des sous-pixels se mélange naturellement et se diffuse légèrement ; la zone d’échantillonnage se comporte donc comme si elle était plus grande que le sous-pixel physique
- La zone d’échantillonnage doit aussi déborder hors du pixel et se mélanger avec la lumière des sous-pixels des pixels voisins
- Easy Scalable Text Rendering d’Evan Wallace considère qu’un flou horizontal est nécessaire après l’anticrénelage sous-pixel, ce qui produit en pratique le même effet que de considérer les éléments sous-pixel comme plus grands et chevauchants
Les logiciels doivent pouvoir connaître les informations de sous-pixels des écrans
- Si l’on pouvait accéder à la structure sous-pixel arbitraire d’un écran, la qualité générale de l’anticrénelage sous-pixel et du rendu de texte pourrait être améliorée
- Si ces informations étaient fournies via des protocoles d’affichage communs, même les écrans à agencement standard pourraient bénéficier d’un rendu plus fin adapté au matériel
- Les fabricants d’écrans n’auraient pas à éviter d’expérimenter de meilleures structures sous-pixel à cause des problèmes de rendu de texte
- Samsung a modifié la structure sous-pixel entre les QD-OLED G8 et G9 pour réduire ce type de problème, et les franges colorées sont fréquemment signalées sur les LG WOLED et Samsung QD-OLED
- Ce problème peut potentiellement être traité par une correction logicielle plutôt que par un remplacement matériel
Valeur pratique du rendu de glyphes en temps réel
- Une bonne UI et une bonne qualité de texte peuvent améliorer la qualité perçue d’un produit
- Dans les jeux, les zones de texte, menus, titres et notifications attirent souvent le regard de l’utilisateur ; une mauvaise qualité de texte peut donc affecter l’expérience autant qu’une scène 3D mal rendue
- Les séries Persona, Metaphor: ReFantazio et Nier: Automata sont de bons exemples d’UI et de mise en scène typographique
- Chercher à améliorer la qualité du rendu de glyphes en temps réel a une valeur concrète, aussi bien pour les UI que pour le rendu dans les jeux
1 commentaires
Avis sur Hacker News
Qu’est-il arrivé au point du j en italique dans la première vidéo ?
Le rendu de polices en sous-pixels est important pour la lisibilité, mais comme le souligne l’article, il est dommage qu’on ne puisse pas obtenir la spécification de l’agencement des pixels à partir des standards d’affichage existants.
Le monde est passé de plus en plus aux écrans de type Retina, où le rendu sous-pixel n’a presque plus de raison d’être.
Il y a beaucoup de complications : les captures d’écran sont liées à un agencement précis des sous-pixels, et l’agrandissement/réduction des bitmaps devient aussi difficile.
C’était une innovation transitoire de l’ère LCD, entre le CRT et le Retina ; aujourd’hui, cela ressemble plutôt à une technologie tournée vers le passé. Apple avait de bonnes raisons de la retirer de macOS il y a quelques années.
Je me demande si ce sont les fabricants d’écrans qui ne l’implémentent pas. Quoi qu’il en soit, pour les modèles d’écrans les plus courants, c’est une information qu’on pourrait facilement déduire et stocker dans une base de données d’informations matérielles.
L’article est excellent, et il renvoie aussi vers un « subpixel zoo » montrant divers exemples : https://geometrian.com/resources/subpixelzoo/
Même dans les cas inévitables où un moniteur signale un mauvais agencement, cette approche reste nécessaire.
De simples polices bitmap sans antialiasing ou des polices vectorielles hintées offrent déjà une très bonne lisibilité.
Cela ne devient important que pour les langues dont les caractères comportent des détails très complexes, comme le chinois ou le japonais.
GTK4 a abandonné le rendu sous-pixel RGB en déplaçant le rendu vers le GPU.
J’avais entendu dire que des décisions centrées sur le GPU rendaient difficile le maintien du rendu sous-pixel RGB, mais l’article montre que c’est possible.
Dans ce cas, les raisons de GTK étaient peut-être ailleurs, ou bien la solution proposée a des inconvénients, ou ne s’intègre pas bien à la pile existante.
Si vous vous intéressez à la façon d’implémenter SDF et MSDF dans WebGL / WebGPU, vous pouvez consulter le tutoriel que j’ai écrit : https://infinitecanvas.cc/guide/lesson-015#msdf
J’ai déjà porté des exemples JavaScript vers Rust : on ne peut pas simplement copier-coller, mais les API sont assez proches pour que le portage soit facile, ce qui est idéal pour apprendre.
Cela donne aussi l’occasion de se familiariser avec la documentation de WGPU.
J’aime créer des tutoriels liés au GPU et j’aimerais les structurer de cette façon ; je me demande si c’est un template existant ou une partie d’un cours.
La bibliothèque Slug est un middleware commercial qui implémente ce type de rastériseur de glyphes sur GPU.
[1] : https://sluglibrary.com/
Ce serait amusant de créer une version open source en wgpu en utilisant une partie du parsing de polices et de la mise en page de cosmic-text, mais ce ne serait plus du tout amusant si Slug finissait par nous poursuivre en justice.
Le GPU semble avoir une capacité pratiquement infinie à dessiner des sommets et des pixels ; je ne comprends donc toujours pas pourquoi il faudrait rendre le texte hors ligne, le stocker dans un atlas, et aller jusqu’à utiliser des astuces comme les SDF.
L’article dit aussi qu’il écrit les courbes des glyphes dans un atlas ; je me demande pourquoi le shader ne pourrait pas rendre le texte directement.
Il doit sûrement exister une façon de convertir des Béziers en maillage de triangles. Je suis justement en train de commencer un moteur de rendu de texte GPU pour une application de CAO, donc j’espère bientôt comprendre pourquoi.
Le GPU est rapide, mais pas infiniment, et il est très fort pour échantillonner des textures déjà rendues.
Ce n’est pas seulement une question de vitesse, mais aussi de consommation d’énergie. Si l’on atteint déjà la fréquence de rafraîchissement de l’écran, des performances supplémentaires n’améliorent pas la réactivité, mais peuvent prolonger l’autonomie.
En rendu, il n’existe pas de « suffisamment rapide » : aller plus vite apporte toujours un bénéfice.
Les architectures GPU modernes sont toutes mauvaises pour traiter une géométrie très dense. Dans ce cas, envoyer simplement des triangles au GPU est très inefficace par rapport à un atlas ou à d’autres techniques.
La plupart des GPU dispatchent les pixel shaders par groupes de 4. Si tous les triangles font 1 pixel, trois threads de shader ne contribuent pas à la sortie visuelle.
C’est ce qu’on appelle le quad overdraw. En plus, on passe beaucoup de temps dans le traitement des sommets sans vraie raison.
C’est possible, mais on sacrifie une partie du budget de frame et on augmente la consommation d’énergie sans grand bénéfice.
L’auteur utilise un atlas parce qu’il supersample les courbes de Bézier jusqu’à 512 échantillons par pixel, ce qui est très coûteux.
À la place, une approche consistant à calculer l’intégrale d’intersection entre la zone de la courbe de Bézier et la zone de sous-pixel pourrait être bien plus rapide, fonctionner en temps réel sans atlas, et sans doute être plus précise que le supersampling.
Et on veut presque toujours utiliser ce temps ailleurs.
Plus on a besoin de temps GPU, plus le matériel minimal requis doit progresser rapidement. Le texte est beau et important, mais peut-être pas au point de perdre des utilisateurs ou des clients.
Cela semble pire que le simple constat selon lequel « les nouveaux OLED sont beaux, mais leur structure de sous-pixels non standard pose des problèmes de franges de couleur »
D’après ce que j’ai compris, ce n’est pas simplement non standard : il existe plusieurs agencements de sous-pixels incompatibles entre eux sur les OLED
C’est pourquoi FreeType n’a pas implémenté le rendu sous-pixel pour l’OLED, et c’est une raison d’éviter l’OLED si l’on doit travailler avec du texte
Ce n’est pas non plus seulement un problème de FreeType : les toolkits GUI comme Qt et GTK doivent aussi s’aligner. Je ne sais pas vraiment s’il y a des avancées vers une solution
Ce serait bien de pouvoir accéder à la structure de sous-pixels d’un moniteur arbitraire, et ce type d’information devrait peut-être être transmis via EDID
Par exemple, mon ordinateur portable a un agencement BGR vertical, que FreeType et KDE prennent bien en charge
J’ai l’impression que les agencements étranges viennent souvent du fait que, sur les écrans HDR, il faut utiliser des tailles différentes selon les couleurs pour éviter que certaines, notamment le bleu, ne se dégradent trop vite
Travail très impressionnant
Pour les personnes qui ne connaissent pas bien le domaine, Valve a créé le rendu de texte SDF pour les jeux et a publié en 2007 un article fondateur sur le sujet
C’est une technique encore aujourd’hui très largement utilisée dans les jeux vidéo, quasiment sans modification
En 2012, Behdad Esfahbod a créé Glyphy, une implémentation SDF fonctionnant sur GPU avec OpenGL ES, largement saluée pour ses performances et de nouvelles fonctionnalités comme la transformation rapide du texte, mais elle n’a pas été largement adoptée
Les systèmes d’exploitation modernes et les navigateurs web préfèrent s’appuyer sur la rastérisation TrueType façon années 1990 plutôt que sur ce type de technique
C’est une approche légère et efficace, mais comme on le voit dans l’article, elle ne permet pas l’alignement sous-pixel ni les agencements de sous-pixels arbitraires ; le zoom a un coût élevé en performances, et les transformations complexes comme l’inclinaison, la rotation ou les transformations 3D ne peuvent pas être effectuées dans le moteur de rendu de texte
Si l’on a besoin de texte pivoté ou transformé, il faut rééchantillonner un bitmap, ce qui détruit toutes les petites caractéristiques qui assurent la lisibilité et donne un résultat peu agréable
Si les progrès sont lents, c’est peut-être parce que la quantité de travail et les risques sont trop importants par rapport aux gains. Imaginer réécrire un moteur de navigateur web moderne avec du rendu de texte accéléré par GPU n’a rien d’anodin
Le rendu des glyphes n’est qu’une partie du problème, la gestion des retours à la ligne en est une autre. Cela peut être lent, car il faut beaucoup de communications entre CPU et GPU, et l’intégration profonde entre le logiciel et le GPU est aussi difficile
Cette approche offre des performances bien meilleures que le fait de forcer le problème à rentrer dans le pipeline de rendu 3D matériel, comme avec SDF
Safari l’est probablement aussi, mais je ne peux pas l’affirmer de source directe
L’idée selon laquelle l’état de l’art ou les implémentations livrées aux utilisateurs n’auraient pas progressé est fausse
SDF encode la distance locale (Distance) entre un pixel donné et le bord du caractère sous forme d’un champ (Field), c’est-à-dire un tableau bidimensionnel de données, et indique par un bit de signe (Sign) si cette distance se situe à l’intérieur ou à l’extérieur du caractère
Chaque caractère possède une petite carte de données ; elles sont regroupées sous forme de fichier image adapté au GPU, et un shader de rendu SDF les utilise avec un fichier descriptif indiquant où trouver la sous-image de chaque caractère
Ce type de définition des caractères est très robuste face à l’interpolation linéaire entre les valeurs du champ, ce qui permet un agrandissement presque parfait même avec des cartes de résolution relativement faible. Les GPU sont aussi efficaces pour interpoler les valeurs de pixels d’une carte
Mais le point important est que ces cartes doivent être prétraitées, pendant le développement, pour tous les caractères que l’on veut rendre à partir du système de polices existant. C’est nécessaire pour chaque caractère pris en charge par la police
Cela représente beaucoup moins de données que de rendre tous les caractères sous forme de police bitmap haute résolution, mais beaucoup plus que les définitions de contours de glyphes elles-mêmes
Un système qui veut prendre en charge tous les textes possibles dans le monde, comme un système d’exploitation ou un navigateur, ne peut pas utiliser SDF comme système de rendu de texte. Il faudrait des cartes SDF pour tout le jeu de caractères Unicode, ce qui deviendrait trop volumineux
Les jeux s’y prêtent bien parce qu’ils peuvent généralement se contenter d’une localisation imparfaite, ou parce qu’ils n’ont pas à afficher du texte totalement arbitraire
À l’origine, SDF ne peut pas non plus prendre en charge les emoji, car il n’encode que la distance jusqu’au bord du glyphe et ne contient pas d’informations de couleur à l’intérieur du glyphe
Il existe bien une version améliorée, Multichannel SDF, qui prend en charge plusieurs couleurs, mais le nombre total de couleurs reste limité
En pratique, si l’on examine de près un jeu qui utilise SDF pour le texte en jeu et qui dispose aussi d’un système de chat où une communauté mondiale interagit, il est probable que le rendu du texte en jeu et celui du texte du chat soient différents
D’après https://keithclark.co.uk/articles/gpu-text-rendering-in-webk... (2014), « lorsqu’un élément est promu sur le GPU dans les versions actuelles de Chrome, Safari ou Opera, il perd l’anticrénelage sous-pixel et le texte est rendu en niveaux de gris »
Dans ce cas, je me demande ce qui manque. Si l’on prend cette phrase au pied de la lettre, il me semble qu’au moins une partie de l’étape qui va d’une chaîne UTF-8 à un bitmap pourrait être effectuée sur le GPU
Travail impressionnant.
Mais, personnellement, je pense que le lissage sous-pixel n’a pas grand intérêt. C’était un hack acceptable dans les années 2000, quand on utilisait des moniteurs 72 dpi, mais sur les écrans Retina modernes, c’est difficile à percevoir, et on récupère plusieurs inconvénients pour une amélioration minime.
Cela ne fonctionne que sur un arrière-plan opaque, on ne peut pas appliquer d’effets comme le redimensionnement, le miroir ou le flou au résultat rastérisé, et les captures d’écran rendent moins bien lorsqu’on les regarde sur un autre écran.
Selon l’enquête matérielle de Firefox [1], 16 % des utilisateurs utilisent un écran d’une résolution de 1366x768.
Ce n’est pas seulement une question de vieux matériel : des moniteurs et ordinateurs portables 96 dpi sont encore produits aujourd’hui.
[1]: https://data.firefox.com/dashboard/hardware
Les autres arguments ne pèsent pas lourd face au meilleur rendu qu’apporte le rendu sous-pixel là où il est applicable.
Il est important de noter que les SDF calculent la distance en pixels jusqu’au bord le plus proche, tandis que les moteurs de rendu de polices traditionnels calculent la couverture du pixel.
La couverture du pixel est optimale. Pour les petites polices, les SDF peuvent rendre mal aux endroits où les bords se rejoignent.
C’est peut-être moins problématique sur les écrans à PPI élevé. J’ai implémenté moi-même un moteur de rendu SDF, et le résultat était moins bon que FreeType.
En revanche, il est juste de dire que les champs de distance posent problème aux intersections, ou plus généralement dans les angles vifs.
On peut l’atténuer dans une certaine mesure en utilisant plusieurs champs de distance et en rendant leur intersection. Par exemple : https://github.com/Chlumsky/msdfgen.