Et si au lieu de définir un maillage comme une série de sommets et d’arêtes dans un espace 3D, vous pouviez le décrire comme une fonction unique ? La fonction la plus simple renverrait la distance signée au point le plus proche (négatif signifiant que vous étiez à l’intérieur de l’objet). C’est précisément ce qu’est une fonction de distance signée (SDF). Un champ de distance signé (également SDF) est juste une grille de voxels où le SDF est échantillonné à chaque point de la grille. Tout d’abord, nous discuterons des SDF en 2D, puis nous passerons à la 3D.
SDF en 2D
Une fonction de distance signée en 2D est plus simple à raisonner, nous allons donc la couvrir en premier. En outre, il est utile pour le rendu des polices dans des scénarios spécifiques. [Vassilis] de [Render Diagrams] a une belle démo sur les SDF bidimensionnels qui couvre les bases. La technique naïve de rendu consiste à créer une grille et à calculer la distance à chaque point de la grille. Si la distance est supérieure à la taille de la cellule de la grille, le pixel n’est pas coloré. Des valeurs négatives signifient que le pixel est coloré car le centre du pixel se trouve à l’intérieur de la forme. En augmentant la taille de la grille, vous pouvez obtenir de meilleures approximations de la forme réelle du SDF. Alors, pourquoi l’utiliser plutôt qu’une approche vectorielle plus traditionnelle ? L’avantage est que la forme est représentée par une seule formule calculée en plusieurs points. La plupart des ordinateurs modernes sont extraordinairement bons pour calculer la même chose des milliers de fois avec des paramètres légèrement différents, souvent en utilisant le GPU. GLyphy est un moteur de rendu de texte basé sur SDF qui utilise OpenGL ES2 comme shader, comme discuté lors de la conférence Linux en 2014. Freetype a même fusionné un moteur de rendu SDF écrit par [Anuj Verma] retour en 2020.
Comment les SDF sont-ils définis ? Un cercle est facile à définir car c’est la longueur du vecteur jusqu’au centre moins le rayon du cercle. Les rectangles sont un peu plus compliqués, mais [Ronja] a une présentation pratique du concept. Il est facile de déterminer la distance à partir d’une ligne infinie avec une certaine épaisseur (T) centrée en (0,0). Prenez simplement la valeur absolue de la distance à l’un des bords ou abs(T – sample_point.x). Il serait naïf de calculer ces deux valeurs et de prendre ensuite la longueur du vecteur résultant. Cela génère des distances incorrectes à l’intérieur de la forme. Au lieu de cela, la bonne façon de procéder consiste à calculer la distance intérieure et extérieure et à les plafonner afin qu’ils ne retournent pas les panneaux. Le rectangle ci-dessous montre des lignes représentant la distance (le rouge étant négatif).
Les rotations, les mises à l’échelle et les transformations modifient le point d’échantillonnage avant qu’il ne soit évalué. Cela permet certaines propriétés remarquables, telles que la mise en miroir ou la répétition à l’infini. Fusionner plusieurs objets est aussi simple que de prendre le minimum entre eux. Une intersection est juste une opération max. Vous pouvez interpoler en douceur entre les objets en interpolant linéairement les distances. Les biseaux, les chanfreins et les mélanges lisses sont tous triviaux avec quelques calculs. Dériver chacune de ces équations est un exercice laissé au lecteur, mais des vidéos et des articles existants vous guident à travers chaque primitive.
Nous avons même un exemple de SDF sur Shadertoy du logo Hackaday avec lequel vous pouvez jouer (cliquez dessus pour voir une visualisation de la distance). Shadertoy est un terrain de jeu qui vous permet de jouer avec le code de shader GLSL directement dans votre navigateur.
SDF en 3D
Plutôt que des triangles, des maillages ou des voxels, un SDF 3D est une forme définie mathématiquement avec des détails potentiellement infinis. [Inigo Quilez] a créé une vidéo fantastique qui détaille comment peindre une belle scène de paysage avec des SDF, et cela vaut bien la peine d’être regardé. Il a également un Shadertoy avec lequel vous pouvez jouer directement dans votre navigateur.
Bien entendu, les SDF présentent certains inconvénients par rapport aux maillages traditionnels. Leur déformation est délicate et les déformations doivent être intégrées au modèle réel. C’est-à-dire sans quelque chose comme un espace de déformation non linéaire, comme cet article en parle. Un autre inconvénient est que les performances peuvent être nettement plus lentes que la rastérisation. Grands SDF comme selfie girl par [Inigo] (voir ci-dessous) sont assez éprouvants même sur les gros GPU de bureau.
En termes de code, le rendu de l’image est plus simple que vous ne le pensez, avec un marcheur de rayons adapté à seulement 135b de WebGL. Certaines bibliothèques pratiques, telles que hg_sdf, facilitent l’ajout de SDF à la scène de démonstration. Comme leur code est minuscule, il s’agit d’une technique courante, comme nous l’avons récemment couvert. [SimonDev] a une excellente vidéo qui explique Ray Marching de manière claire et concise.
La CAO est une autre voie courante pour SDF car elle peut facilement générer des formes chanfreinées et organiques complexes qui seraient difficiles à décrire dans un système basé sur des contraintes. En particulier, les booléens deviennent beaucoup plus simples dans un espace SDF par rapport à un espace maillé. Plusieurs projets sur GitHub offrent une excellente expérience de développeur avec des cloches et des sifflets inclus. Généralement, l’algorithme des cubes en marche avec un octree est utilisé pour transformer le SDF en géométrie de maillage réelle pour l’impression 3D.
Conclusion
Les fonctions de distance signées sont incroyablement puissantes et assez accessibles. Vous pouvez commencer à jouer avec eux dans votre navigateur, les bibliothèques C++, Python ou dans quelques packages CAO différents. Pourquoi ne pas les amener dans un environnement restreint ou commencer à créer de l’art sans rien modéliser ?