Le site est en construction. Des incohérences peuvent subsister.

Bruitage d'images vectorielles

Partagé le par

Introduction

Hier est paru un article sur CSS Tricks par Bence Szabó, traitant de la création de motifs à base de filtres SVG. Recourir à dégradés CSS pour générer des motifs ne m'est pas inconnu, mais je n'ai jamais pris le temps de me pencher réellement sur les techniques équivalentes en SVG. Or le champ des possibles qu'offre SVG me semble bien plus large, notamment grâce à la possibilité de générer du bruit. J'ai donc voulu essayer, et tel un enfant faisant son premier dessin, j'ai représenté... le soleil.

Ciel étoilé

J'ai repris quasiment telle quelle l'idée du fond étoilé généré pseudo-aléatoirement avec du bruit via l'élément <feTurbulence />. J'ai juste ajusté les différents poids de la matrice pour avoir des étoiles de couleurs variées, quoiqu'essentiellement jaunes, au lieu d'être systématiquement blanches.

Code SVG et rendu d'un bruit de fond
<filter id="sky">
	<feTurbulence type="fractalNoise" baseFrequency=".25" />
	<feColorMatrix values="32 0 0 0 -24
	                       24 0 0 0 -18
	                       16 0 0 0 -12
	                       0 0 0 0 1" />
</filter>
<rect width="100%" height="100%" filter="url(#sky)" />

Au passage, en voulant indenter la chose, j'ai découvert à mes dépens que Webkit n'apprécie pas les espaces en début et fin de la valeur de l'attribut values="" de l'élément <feColorMatrix />. La solution de contournement est vite trouvée...

Soleil

Un simple disque jaune pour dépeindre le soleil aurait fait tâche sur ce fond étoilé. Pour réprésenter son rayonnement et éviter d'avoir un contour trop net, j'ai ajouté un dégradé externe variant du jaune au rouge en partant du bord.

Code SVG et rendu d'un disque jaune rayonnant un dégradé jaune-rouge
<radialGradient id="gradient" fr="33.3%" r="50%">
	<stop offset="3.125%" stop-color="#ff0f" />
	<stop offset="6.25%" stop-color="#fc0c" />
	<stop offset="12.5%" stop-color="#f909" />
	<stop offset="25%" stop-color="#f606" />
	<stop offset="50%" stop-color="#f303" />
	<stop offset="100%" stop-color="#f000" />
</radialGradient>
<circle cx="50%" cy="50%" r="96" fill="url(#gradient)" />

Mieux. Un peu trop parfait en fait. Comment faire pour avoir une forme un peu moins ronde ? Il se trouve que l'élément <feDisplacementMap/> permet précisément de créer un effet de distortion bidirectionnelle sur une image. Et en lui donnant du bruit en entrée, on peut obtenir une sorte de blob à la forme assez irrégulière ! N'en abusons pas, tout de même.

Code SVG et rendu d'un blob
<filter id="sun">
	<feTurbulence type="fractalNoise" baseFrequency=".125" numOctaves="2" />
	<feDisplacementMap xChannelSelector="R" yChannelSelector="G" in="SourceGraphic" scale="16" />
</filter>
<circle cx="50%" cy="50%" r="96" filter="url(#sun)" />

Pas mal ! On croirait voir les éruptions solaires ionisant la couronne du soleil ! Il ne manque plus que la touche finale : animer le tout. Mais pour garder une animation régulière avec une échelle de bruit assez uniforme, la technique consacrée, bien qu'assez simple à mettre en place, semble vraiment relever de la magie. On peut en voir une démonstration sur Codepen par Michael Mullany. Au lieu d'animer la fréquence, l'astuce est de passer le bruit à travers un filtre de couleurs qui opère une rotation progressive sur la teinte selon le cercle chromatique. Cela permet d'exploiter le bruit généré sur le troisième canal de couleur, au lieu de se limiter à deux comme c'était le cas précédemment, mais aussi à l'animation de boucler.

Code SVG et rendu d'un blob animé
<filter id="sun">
	<feTurbulence type="fractalNoise" baseFrequency=".125" numOctaves="2" />
	<feColorMatrix type="hueRotate">
		<animate attributeName="values" from="0" to="360" dur="4s" repeatCount="indefinite" />
	</feColorMatrix>
	<feDisplacementMap xChannelSelector="R" yChannelSelector="G" in="SourceGraphic" scale="16" />
</filter>
<circle cx="50%" cy="50%" r="96" filter="url(#sun)" />

Je reste étonné du si peu de code nécessaire pour parvenir à un tel effet. Assemblons tout ça et jetons un œil au résultat final sans plus attendre !

Rendu

Rendu du soleil devant un ciel étoilé (voir le code source)

Une démonstration est aussi disponible ici.