Créer un effet crayon en SVG

Mon jeu Dragons Abound crée des cartes au format graphique vectoriel SVG. Les graphiques vectoriels ont de nombreuses fonctionnalités (par exemple, un zoom sans perte), ce qui est pratique pour les cartes. En outre, les graphiques vectoriels sont bons pour créer des lignes claires, telles que les contours d'encre:


En revanche, les graphiques vectoriels ne sont pas très bons pour créer des textures avec de petits détails non répétitifs. Dans les graphiques vectoriels, chaque élément rendu est représenté par une description de sa taille, sa forme, son emplacement, sa couleur, etc. Afin de présenter de nombreux petits détails non répétitifs, il est nécessaire de décrire un grand nombre d'éléments. Par exemple, pour une ligne de crayon


des dizaines de milliers d'éléments différents seront nécessaires. En fait, chaque point gris de l'image sera défini séparément. D'autres éléments, comme les images floues, sont encore plus problématiques.

Il s'agit d'une limitation assez grave des graphiques vectoriels, donc des astuces ont été ajoutées à SVG qui vous permettent de reproduire plus efficacement certains de ces effets de texture. J'explorerai certaines de ces fonctionnalités SVG pour créer un effet de ligne de crayon. Bien sûr, il existe de nombreuses solutions plus complexes pour recréer des lignes de crayon. Des articles scientifiques entiers ont été écrits sur ce sujet . Mais j'espère juste créer un filtre assez simple qui fournira un résultat acceptable.

Comme toujours, je préférerais emprunter ou modifier un filtre créé par quelqu'un de plus talentueux que moi, mais dans ce cas, il y avait une pénurie incroyable de filtres à crayons vectoriels qui peuvent être utilisés pour l'inspiration. (Une musique d'avertissement inquiétante retentit: il peut y avoir des raisons à cela.) Par conséquent, en fait, je ne peux compter que sur moi-même.

Plus tôt, j'ai écrit sur les possibilités de Dragons Aboundpour créer des lignes "manuscrites". Fondamentalement, j'ai envisagé la possibilité d'éviter les lignes droites mathématiquement et de créer des lignes avec de légères déviations qui ressemblent plus à ce qui pourrait être dessiné par la main d'une personne. Au début de l'article, des exemples d'illustrations de montagnes sont présentés. Pour créer un style d'illustration à l'encre, cela suffit, mais ne convient pas pour créer une ligne de crayon, car il manque une texture de crayon.

Si vous regardez les lignes de crayon ci-dessus et ci-dessous:


vous remarquerez de nombreuses fonctionnalités qui distinguent les traits de crayon des lignes d'encre (ou des lignes dessinées par un ordinateur). La différence la plus importante est qu'ils ont une texture résultant de la façon dont le crayon interagit avec le papier. Le papier est granuleux et le crayon laisse généralement du graphite sur les parties hautes du grain, tandis que les parties basses restent blanches. Sur papier grossier, la texture est plus visible; le dessin du carton est si fin qu'il ne crée presque pas de texture. Deuxièmement, les bords des lignes de crayon sont assez vagues. Ceci est encore largement dû à l'inégalité du papier et de la pointe du crayon; cela conduit au fait que le long du bord de la ligne reste une quantité différente de graphite.

(Bien sûr, il y a d'autres effets. La trace du crayon se superpose, donc elle devient plus foncée aux intersections des traits. Les traits eux-mêmes varient en pression et cela peut changer l'obscurité du trait sur toute sa longueur. Dans cet article, je me concentrerai principalement sur la reconstruction de la texture du papier.)

Pour J'ai commencé par préparer de simples lignes grises:


J'ai dessiné des lignes «manuscrites» d'une épaisseur de 4, 2 et 1 pixel. Malheureusement, les effets SVG sont généralement différents pour les lignes de différentes longueurs, donc je voulais comparer l'effet sur différentes tailles.

La fonction principale fournie par SVG pour ajouter des effets de texture est appelée filtres . Les filtres sont appliqués après le rendu de l'effet vectoriel et changent son apparence. Les filtres conventionnels peuvent effectuer des actions telles que changer la couleur d'un objet, y ajouter du bruit, etc. Les filtres sont un sujet assez déroutant avec une syntaxe complexe, donc je ne donnerai pas un tutoriel complet sur la façon de les utiliser, mais je vais expliquer suffisamment en détail pour que ce que j'ai fait soit clair. Et à la fin de l'article, je donnerai un lien vers Codepen avec un filtre afin que vous puissiez l'expérimenter vous-même.

Tout d'abord, je vais essayer de changer les bords des lignes afin qu'elles ne soient pas lisses, mais présentent des irrégularités caractéristiques du grain du papier. Je vais le faire en déplaçant les pixels de la ligne. L'élément de filtre effectuant cette tâche est appelé «feDisplacementMap»; il déplace chaque pixel en fonction des valeurs d'une autre image. Puisque nous voulons que chaque pixel se déplace de manière aléatoire mais uniforme, nous devons transmettre du bruit à feDisplacementMap pour contrôler le mouvement. Heureusement, SVG a un autre élément de filtre appelé «feTurbulence» qui est spécifiquement conçu pour créer du bruit. Nous pouvons donc combiner deux filtres pour rendre les bords des lignes plus rugueux.

L'amplitude et la grossièreté de la ligne peuvent être contrôlées par les paramètres de la carte de déplacement et la génération de bruit. Malheureusement, le décalage est indiqué en unités absolues, sans rapport avec la taille de la ligne. J'ai sélectionné les paramètres, essayant de trouver quelque chose qui convient à toutes les largeurs de ligne, mais avec une augmentation de l'échelle de décalage, vous pouvez remarquer le problème:


Maintenant, le déplacement est si important qu'il peut déplacer toute la ligne, et pas seulement changer ses bords. Cet effet est encore plus visible sur les lignes fines. Dans cet exemple, une ligne d'une largeur de 4 pixels semble fondamentalement comme si le bord est rugueux et des distorsions sont déjà perceptibles sur une ligne d'une épaisseur de 2 pixels. Autrement dit, je dois choisir une valeur qui ne crée pas de distorsions dans les lignes fines.

Lors d'un zoom avec une augmentation standard du jeu, l'effet ressemble à ceci (après avoir sélectionné des paramètres pour améliorer l'effet):


À cette échelle, de nombreux bords rugueux deviennent des taches et des points. Ce n'est pas un effet très désagréable, et cela rappelle un peu un trait de crayon. (Cependant, en général, les filtres SVG semblent avoir des problèmes de mise à l'échelle - dans de nombreux cas, lorsqu'ils sont zoomés, ils ont l'air bien, mais ils sont soumis à un algorithme de redimensionnement médiocre lorsqu'ils s'éloignent.)

Voici à quoi ressemble l'effet lors du dessin de montagnes (effet crayon à gauche):


Pas si terrible, mais la ligne a des artefacts tranchants qui semblent un peu étranges. Et lorsque l'effet est appliqué à des lignes fines et étroitement espacées, elles se chevauchent et fusionnent en conséquence:


Je le répète, ce n'est pas si terrible, et les ombres sur les montagnes au crayon ressemblent donc beaucoup à celles dessinées au crayon, si vous avez besoin d'un tel effet.

Cette solution ajoute de la rugosité aux contours du trait de crayon, mais ne change pas la couleur uniforme du trait. La texture est également présente à l'intérieur de vrais coups de crayon, car le graphite laisse des taches sur le papier de manière inégale.

Pour ajouter de la texture à l'intérieur du trait, j'utilise un filtre SVG puis je combine le bruit avec le trait:


Lors d'un zoom avant, vous pouvez voir que l'intérieur de chaque trait est maintenant rempli d'une texture pseudo-graphite. Voici à quoi cela ressemble à une échelle normale:


Assez bien, surtout sur les lignes épaisses. Voici à quoi cela ressemble lorsque vous dessinez des montagnes:


A cette échelle, tout n'est pas très bon. Notez que ce filtre réduit également l'obscurité des lignes; c'est un résultat naturel de l'ajout de bruit blanc aux lignes. Dans une certaine mesure, ce problème peut être atténué en augmentant le contraste du bruit, de sorte que certaines parties de la ligne de compensation deviennent plus sombres:


Mais comme les couleurs de la ligne sont déjà assez sombres, cela détruit largement l'effet de "crayon". Par conséquent, si j'utilise cela, je dois sélectionner les paramètres pour créer un équilibre agréable.

De toute évidence, les deux solutions peuvent être combinées. Avec une augmentation, le résultat semble plutôt bon:


De la ligne de crayon, nous attendons à la fois un bord rugueux et une texture interne. Sur une échelle standard, tout n'est pas si bon:


en raison d'artefacts tranchants qui sont apparus à cette échelle.

Une bonne astuce pour améliorer cette texture serait d'ajouter une texture de papier à l'arrière-plan:


Maintenant, l'œil perçoit la texture uniforme sur toute l'image. Même à un niveau très implicite, cela aide à tromper l'œil et à convaincre que la texture de la ligne est causée par l'interaction avec le papier.

Voici un exemple d'utilisation de ce filtre sur une carte (avec une texture de papier):


En général, tout n'est pas mal, mais avec une étude détaillée, il semble que partout vient d'ajouter du bruit. Avec une augmentation de 200%, les artefacts deviennent encore plus évidents:


Une autre façon de créer un bord rugueux d'une ligne de crayon est de dessiner plusieurs fois la ligne avec des écarts légèrement différents et une opacité réduite. Au centre de la ligne, où plusieurs versions se croisent, la densité sera proche de la densité de la ligne d'origine; aux bords extérieurs, où parfois il n'y a qu'une partie des lignes, l'opacité sera plus faible et les bords seront moins lisibles.

En général, pour implémenter une telle solution à l'aide de filtres SVG, vous devez utiliser feTurbulence et feDisplacementMap ensemble pour créer une version déformée de la ligne. Cependant, pour faire cela plusieurs fois et combiner toutes les lignes à la fin, vous avez besoin d'un ensemble de primitives feBlend. Si, par exemple, nous mélangeons trois copies, nous devons réduire de manière appropriée l'opacité des lignes. (Je ne sais pas trop comment calculer spécifiquement l'opacité correspondante, mais je pense que cela peut être la racine cubique de la luminosité de la ligne.)

Cela crée l'effet (trois lignes avec une augmentation):


Cette approche présente quelques inconvénients. Le filtre a une déviation fixe, il affecte donc plus fortement les lignes étroites, et à certains points, on peut voir que la ligne à un pixel est complètement divisée. Deuxièmement, c'est un filtre assez complexe qui crée trois écarts distincts et les combine; cela peut être très lent sur des images complexes comme les cartes Dragons Abound .

Voici à quoi cela ressemble à une échelle standard:


À mon avis, cela ne ressemble pas tout à fait à un crayon, mais il élimine mieux les artefacts tranchants de la solution précédente.

Cette approche peut être combinée avec le filtre de texture interne décrit ci-dessus et ajouter de la texture à l'intérieur des lignes de crayon, ainsi que de la texture du papier:


Voici à quoi cela ressemble après avoir appliqué à la montagne:


Ce filtre a tendance à répartir les lignes plus fortement que l'autre filtre, ce qui les rend essentiellement plus épaisses. Parfois, il génère un effet d'esquisse avec plusieurs lignes, ce qui n'est pas si mal.

Voici un exemple d'utilisation de ce filtre sur une carte:


Il préserve mieux l'obscurité d'origine que le premier filtre, et bien qu'à mon avis il ne ressemble pas exactement à un crayon, l'effet est assez agréable. Avec une augmentation de 200%:


Lorsqu'il est agrandi, ce filtre n'acquiert pas d'artefacts nets du premier filtre. L'effet des lignes qui se croisent sur des lignes fines (par exemple, comme dans l'image d'une forêt) commence à sembler assez artificiel, mais les lignes plus larges (montagnes et rivières) semblent toujours bonnes. Cependant, dans les lignes noires, telles que les rivières, le bruit interne est presque complètement perdu.

J'ai posté ces deux filtres sur Codepen afin que vous puissiez les essayer vous-même. Le premier filtre est ici , le second est ici . Je recommande d'expérimenter avec eux et d'essayer de les améliorer, et si vous obtenez quelque chose de mieux que le mien, faites le moi savoir! J'aimerais avoir un très bon filtre à crayon!

All Articles