Aller au contenu

Bruit de Perlin

Un article de Wikipédia, l'encyclopédie libre.
Bruit de Perlin en deux dimensions.

Le bruit de Perlin est une texture procédurale utilisée comme effet visuel pour augmenter le réalisme apparent dans la synthèse d'image. La fonction a une apparence pseudo-aléatoire, et pourtant tous ses détails visuels sont de taille égale (voir image). Cette propriété permet à cette texture d'être facilement contrôlable. De multiples copies zoomées de bruit de Perlin peuvent être insérées dans des expressions mathématiques pour créer une grande variété de textures procédurales.

Bruit de Perlin redimensionné et combiné à lui-même pour créer un bruit fractal.

Le bruit de Perlin est une primitive utilisée pour la génération de textures procédurales. C'est un bruit de gradient (par opposition aux bruits de valeur) utilisé pour améliorer le réalisme des infographies. La fonction a un aspect pseudo-aléatoire, cependant ses détails sont de la même taille : cette propriété la rend facile à contrôler et à combiner à différentes échelles.

Le bruit de Perlin est souvent utilisé dans les images de synthèse pour des éléments tels que le feu, la fumée ou les nuages.

Les démos utilisent couramment le bruit de Perlin car il est très économe en espace mémoire.

Il est aussi utilisé dans le jeu vidéo. Par exemple, Minecraft utilise le bruit de Perlin pour générer ses mondes.

Développement

[modifier | modifier le code]
Boule de feu générée par "Bruit de Perlin".

Le bruit de Perlin a été développé par Ken Perlin en 1985. À cette époque, après avoir travaillé sur les effets spéciaux de Tron pour MAGI (en) en 1981, il cherchait à éviter le rendu « très artificiel »[1] des images de synthèse. Il commença donc à mettre au point une fonction pseudo-aléatoire de bruit qui remplit les trois dimensions de l'espace[2],[3], avant d'inventer l'année suivante le premier langage de shading (en)[4]. Ses travaux sur les textures procédurales ont valu à Ken Perlin l'Academy Award for Technical Achievement (en) en 1997[5].

Le bruit de Perlin est le plus couramment utilisé à deux, trois, voire quatre dimensions, il peut être défini pour un nombre quelconque de dimensions. L'algorithme se décompose en trois étapes :

  • Définition de la grille avec des vecteurs de gradient aléatoires
  • Calcul du produit scalaire entre le vecteur de gradient et le vecteur distance
  • Interpolation entre ces valeurs

Définition de la grille

[modifier | modifier le code]

Définir une grille à n dimensions. À chaque intersection de la grille (ou sommet), attribuer un vecteur de gradient unitaire, de direction aléatoire et de dimension n.

Par exemple :

  • Pour une grille à deux dimensions (n = 2), on assigne à chaque sommet un vecteur aléatoire du cercle unité.
  • Pour une grille à une dimension (n = 1), on assigne à chaque sommet un nombre aléatoire entre -1 et 1.

Le calcul des gradients (pseudo)-aléatoires en une et deux dimensions est trivial en utilisant un générateur de nombres aléatoires. Pour les dimensions supérieures, une approche Monte Carlo peut être utilisée où les coordonnées cartésiennes aléatoires sont choisies dans un cube unité, les points situés en dehors de la sphère unité sont rejetés et les points restants sont normés.

Produit scalaire

[modifier | modifier le code]

Pour calculer la valeur du bruit en un point P donné, déterminer dans quelle cellule de la grille se trouve P. Pour chaque sommet de cette cellule, calculer le vecteur de distance entre P et le sommet. Calculer le produit scalaire entre le vecteur de gradient au sommet et le vecteur de distance.

Pour un point dans une grille à deux dimensions, il faut calculer 4 vecteurs de distance et 4 produits scalaires, tandis que dans une grille à trois dimensions, il faut calculer 8 vecteurs de distance et 8 produits scalaires. Ceci conduit à une complexité algorithmique .

Interpolation

[modifier | modifier le code]

La dernière étape est l'interpolation entre les produits scalaires calculés aux sommets de la cellule contenant P. Cela a pour conséquence que la fonction de bruit renvoie 0 pour les sommets de la grille.

L'interpolation est effectuée en utilisant une fonction dont la dérivée première (et éventuellement la dérivée seconde) est nulle aux nœuds de la grille . Cela a pour effet que le gradient de la fonction de bruit résultante à chaque nœud de grille coïncide avec le vecteur de gradient aléatoire précalculé. Par exemple, si , un exemple de fonction qui interpole entre la valeur au nœud de grille 0 et la valeur au nœud de grille 1 est

où la fonction smoothstep (en) a été utilisée.

Les fonctions de bruit utilisées dans l'infographie produisent généralement des valeurs comprises dans l'intervalle [-1.0,1.0]. Afin de produire du bruit Perlin dans cet intervalle, la valeur interpolée peut avoir besoin d'être mise à l'échelle par un facteur d'échelle.

Pseudo-code

[modifier | modifier le code]

Voici le pseudo-code de l'implémentation du bruit de Perlin dans un espace à deux dimensions.

 // Fonction lisse de l'intervalle [0.0, 1.0] vers lui-même
 function smoothstep(float w) {
     if (w <= 0.0) return 0.0;
     if (w >= 1.0) return 1.0;
     return w * w * (3.0 - 2.0 * w);
 }
 
 // Fonction d'interpolation lisse entre a0 et a1
 // Le poids w doit être dans l'intervalle [0.0, 1.0]
 function interpolate(float a0, float a1, float w) {
     return a0 + (a1 - a0) * smoothstep(w);
 }
 
 // Fonction de calcul du produit scalaire entre le vecteur de distance et le vecteur de gradient.
 function dotGridGradient(int ix, int iy, float x, float y) {
 
     // Vecteurs de gradient aux intersections de la grille (pré-calculés ou non)
     extern float Gradient[IYMAX][IXMAX][2];
 
     // Calcul du vecteur de distance
     float dx = x - (float)ix;
     float dy = y - (float)iy;
 
     // Calcul du produit scalaire
     return (dx*Gradient[iy][ix][0] + dy*Gradient[iy][ix][1]);
 }
 
 // Calcul du bruit de Perlin au point de coordonnées (x, y)
 function perlin(float x, float y) {
 
     // Coordonnées de la case de la grille dans laquelle se trouve le point
     int x0 = floor(x);
     int x1 = x0 + 1;
     int y0 = floor(y);
     int y1 = y0 + 1;
 
     // Poids pour l'interpolation
     // (On pourrait utiliser des polynômes d'ordre supérieur ou d'autres fonctions lisses)
     float sx = x - (float)x0;
     float sy = y - (float)y0;
 
     // Interpolation entre les coins de la case
     float n0, n1, ix0, ix1, value;
     n0 = dotGridGradient(x0, y0, x, y);
     n1 = dotGridGradient(x1, y0, x, y);
     ix0 = interpolate(n0, n1, sx);
     n0 = dotGridGradient(x0, y1, x, y);
     n1 = dotGridGradient(x1, y1, x, y);
     ix1 = interpolate(n0, n1, sx);
     value = interpolate(ix0, ix1, sy);
 
     return value;
 }

Sur les autres projets Wikimedia :

Notes et références

[modifier | modifier le code]
  1. (en) Ken Perlin, « History », sur www.noisemachine.com (consulté le ).
  2. (en) Ken Perlin, « Controlled random primitive », sur www.noisemachine.com (consulté le ).
  3. (en) Ken Perlin, « coherent noise function over 1, 2 or 3 dimensions », sur nyu.edu (consulté le ).
    Code (en C) de la première version de la fonction, en 1983.
  4. (en) Ken Perlin, « Rapid adoption », sur www.noisemachine.com (consulté le ).
  5. (en) Ken Perlin, « Noise and Turbulence », sur nyu.edu (consulté le ).

Article connexe

[modifier | modifier le code]

Liens externes

[modifier | modifier le code]