Image de couverture du post

2019-06-01 22:22 - Technique

Shader: la parade des éléphants (Dumbo)

L’idée de ce shader est partie d’une discussion sur ShaderToy avec des collègues de boulot. Au départ je voulais recréer la séquence complète mais c’est beaucoup de boulot et techniquement assez redondant (et ça demanderait beaucoup trop de mémoire pour une seule unité ShaderToy). Je me suis donc concentré sur quelques secondes de la séquence.

Quelques détails techniques

La difficulté de ce shader consiste à afficher la forme animée des éléphants. Ajouter des déplacements et de la couleur est très simple une fois cette étape franchie. Pour afficher la forme, je me suis appuyé sur une suite de courbes de Bézier cubiques. Déterminer si un point est à l’intérieur de l’ensemble de courbes est difficile à faire de manière efficace (suffisamment efficace pour le calculer pour chaque pixel en moins de 16ms), mais j’ai réussi à implémenter une version qui termine en temps raisonnable avec la technique suivante: je prends un point à l’extérieur de la forme, et je compte le nombre d’intersections entre la ligne qui relie ce point à un pixel et le polygone qui approxime la forme. Si ce nombre est impair le point est à l’intérieur.

Pour animer les courbes de Bézier, je me suis appuyé sur des courbes de Catmull-Rom (lien en anglais). Mon idée était d’interpoler les points de contrôle des courbes de Bézier dans le temps. Ajouter une dimension temporelle à mes courbes était théoriquement une possibilité, mais en pratique c’est assez difficile à créer correctement. L’avantage des courbes de Catmull-Rom est qu’elles permettent ce créer une courbe lisse sans spécifier explicitement de points de contrôle, à partir des points de passage. J’ai donc créé 4 frames qui composent mon animation, et l’interpolation se charge de faire le reste, en interpolant toujours sur 4 points mais dans un ordre tournant. Et j’avoue avoir été positivement surpris du résultat.

La dernière étape est la compression de ces données. Stocker naïvement chaque point avec 2 nombres flottants coûte 8 octets par point. Mais avec un peu d’astuce et des manipulations de nombres bit par bit j’ai pu stocker 2 points par entier de 4 bits, soit 2 octets par points (4 fois moins que la méthode naïve). J’ai donc pu rentrer l’animation complète dans un tableau de 216 entiers.

Si vous voulez regarder le code du shader, mes images vectorielles ou le code du script d’export, j’ai créé un petit repo sur GitHub.

Où contempler cette création

C’est par ici si vous avez un PC avec carte graphique récente.

Conclusion

Ce shader est relativement simple à créer avec la pipeline graphique complète mais l’implémenter avec seulement un fragment shader était un défi intéressant.

Log in to post a comment.