Introduction
Vous les connaissez tous - leurs noms sont familiers depuis l'école : π (Pi ≈ 3,14159), φ (Phi, le nombre d'or ≈ 1,61803), e (le nombre d'Euler ≈ 2,71828). Mais combien d'entre nous les ont réellement utilisés - pas dans un exercice de maths, mais dans un pipeline de production, pour construire un environnement naturel crédible ?
Ces trois constantes mathématiques ne sont pas des curiosités académiques - ce sont des algorithmes que la nature elle-même utilise depuis des milliards d'années pour optimiser, distribuer et structurer le monde vivant. À leurs côtés se trouve leur compagne naturelle, la suite de Fibonacci, et la règle des 3×3 - une méthode construite au fil d'années de travail en production qui transforme ces principes mathématiques en un workflow concret et reproductible dans Houdini, Blender, Terragen ou Gaea.
Rien de tout cela ne nécessite d'être un expert en code - même si les exemples ci-dessous utilisent les nœuds VEX Wrangle de Houdini. L'essentiel est une façon de penser la création d'environnement : dans la nature, le chaos n'est pas aléatoire. Il est ordonné par la lumière, la croissance, l'espacement, le substrat et l'humidité. Un environnement véritablement naturel n'est pas dessiné à la main - il est généré. Les mathématiques comme ingrédients, la nature comme recette.
π (Pi ≈ 3,14159) - Le nombre des cycles et des cercles
π apparaît partout où une forme tourne, s'enroule, ou est distribuée en anneau : les cernes de croissance des arbres, l'arrangement radial des pétales, les ondulations sur l'eau, les cratères, les zones de végétation autour d'une source d'eau. Tout ce qui est circulaire ou cyclique porte l'empreinte de π. Dans Houdini, il intervient à chaque conversion degrés-radians, chaque courbe de terrain sinusoïdale, et surtout dans le calcul de l'angle d'or - l'outil le plus puissant pour distribuer des éléments sans chevauchement.
L'angle d'or - Quand π rencontre φ
La formule golden_angle = 2π × (1 − 1/φ) ≈ 137.5° est l'un des outils les plus puissants en création d'environnement. Elle combine π et φ pour produire un angle qui, répété indéfiniment, place chaque point sans jamais retomber sur un précédent - exactement ce que font les tournesols, les pommes de pin et les ananas.
// Point Wrangle - Distribution en spirale dorée
float PI = 3.14159265358979;
float phi = 1.61803398874989;
float golden_angle = 2.0 * PI * (1.0 - 1.0/phi); // ~2.3999 rad ~137.5deg
int N = 300;
float R = 15.0; // rayon de distribution max
for (int i = 0; i < N; i++) {
float r = R * sqrt(float(i) / N);
float theta = i * golden_angle;
vector pos = set(r * cos(theta), 0, r * sin(theta));
int pt = addpoint(0, pos);
setpointattrib(0, "pscale", pt, fit(r, 0, R, 0.2, 1.5));
}
Distributions circulaires et anneaux concentriques
Pour des formations en anneau naturelles - végétation autour d'une source d'eau, rochers autour d'un cratère, ronds de sorcières de champignons - π permet de positionner précisément des éléments sur des anneaux concentriques avec une variation naturelle.
// VEX - Distribution en anneaux concentriques (zones humides)
float PI = 3.14159265358979;
// 3 anneaux correspondant aux 3 niveaux de la règle des 3x3
float rings[] = {3.0, 8.0, 13.0}; // rayons de Fibonacci !
float widths[] = {1.5, 2.5, 4.0};
float dist = length(set(v@P.x, 0, v@P.z)); // distance au centre
for (int r = 0; r < 3; r++) {
float inner = rings[r] - widths[r];
float outer = rings[r] + widths[r];
if (dist > inner && dist < outer) {
i@layer = r + 1;
// Angle sur l'anneau - variation par bruit
float angle = atan2(v@P.z, v@P.x);
f@ring_density = abs(sin(angle * rings[r])) * 0.5 + 0.5;
}
}
Courbes sinusoïdales pour le terrain et les rivières
sin(π × x) et cos(π × x) génèrent des courbes douces et naturelles pour les méandres de rivière, les vagues de terrain, ou une variation périodique de densité.
// VEX - Variation de densité sinusoïdale (effet de vague de végétation)
float PI = 3.14159265358979;
float freq = 0.08;
// Ondulation naturelle de la densité
f@density = 0.5 + 0.5 * sin(PI * v@P.x * freq + noise(v@P * 0.3));
// Rivière sinusoïdale
float river_y = 5.0 * sin(PI * v@P.x * 0.05);
float river_dist = abs(v@P.z - river_y);
f@moisture = fit(river_dist, 0, 8, 1, 0); // l'humidité diminue en s'éloignant de la rivière
φ (Phi ≈ 1,61803) - Le nombre d'or
φ est le ratio vers lequel convergent les rapports de termes consécutifs de Fibonacci - la proportion que l'œil humain perçoit comme naturellement harmonieuse, probablement parce qu'il a coévolué avec une nature qui l'utilise partout : la ramification des arbres, l'arrangement des feuilles, les proportions des coquillages.
| Structure naturelle | Mécanisme φ |
|---|---|
| Tournesol / pomme de pin | Spirales selon des ratios de Fibonacci (13/21, 21/34...) pour une densité maximale |
| Phyllotaxie | Angle de divergence ≈ 137,5° (360°/φ²) évite l'ombrage mutuel |
| Coquille de nautile | Spirale logarithmique avec un facteur φ entre chaque révolution |
| Ramification des arbres | Chaque branche se divise selon des ratios proches de φ |
| Ratio de papier A4/A3 | √φ ≈ 1,272 - le même principe de proportion harmonieuse |
Échelles procédurales basées sur φ
// Tailles d'instance basées sur phi - progression harmonieuse
float phi = 1.61803398874989;
int layer = i@layer; // 1, 2 ou 3 (règle des 3x3)
// Chaque niveau est phi fois plus petit que le précédent
float base_scale = 10.0;
f@pscale = base_scale / pow(phi, layer - 1);
// L1 -> 10.0, L2 -> 6.18, L3 -> 3.82
// Variation naturelle +/- 20% autour de la valeur phi
f@pscale *= fit01(rand(@ptnum), 0.8, 1.2);
LOD basé sur φ
// Densité LOD décroissant par phi avec la distance
float phi = 1.61803398874989;
float dist = length(v@P - v@Eye);
// Seuils de distance comme puissances de phi
float d1 = 20.0;
float d2 = d1 * phi; // 32.4m
float d3 = d2 * phi; // 52.4m
float d4 = d3 * phi; // 84.7m
float keep = 1.0;
if (dist > d4) keep = 0.05;
else if (dist > d3) keep = 1.0/pow(phi,3); // ~0.24
else if (dist > d2) keep = 1.0/pow(phi,2); // ~0.38
else if (dist > d1) keep = 1.0/phi; // ~0.62
if (rand(@ptnum) > keep) removepoint(0, @ptnum);
e (Euler ≈ 2,71828) - La constante de la croissance naturelle
e est la base de la croissance et de la décroissance naturelles. Toute population, radiation, ou diffusion qui « croît ou décroît proportionnellement à sa taille » suit une loi en eˣ - la loi fondamentale de la nature derrière une forêt tropicale dense au centre d'une clairière, une végétation s'amenuisant vers les zones rocheuses, ou une densité de biome décroissant avec l'altitude. La fonction f(x) = e⁻ᵏˣ (atténuation de densité) décrit exactement comment la densité d'un élément naturel diminue avec la distance - un grand k donne une atténuation rapide (arbres isolés), un petit k donne une atténuation douce (herbe couvrant tout le terrain).
Masque de densité basé sur la distance
// VEX - Atténuation de densité naturelle avec e
// k contrôle la vitesse d'atténuation
float dist_to_center = length(set(v@P.x, 0, v@P.z));
// Paramètres par niveau (règle des 3x3)
float k_L1 = 0.08; // arbres - atténuation lente
float k_L2 = 0.15; // arbustes - atténuation moyenne
float k_L3 = 0.05; // sol - couvre tout
float density_L1 = exp(-k_L1 * dist_to_center);
float density_L2 = exp(-k_L2 * dist_to_center);
float density_L3 = exp(-k_L3 * dist_to_center);
// Ajouter du bruit pour casser la symétrie parfaite
float n = noise(v@P * 0.05);
density_L1 *= fit01(n, 0.7, 1.3);
if (rand(@ptnum) > density_L1) removepoint(0, @ptnum);
Croissance exponentielle - Végétation vers une source d'eau
// Plus proche de l'eau, plus la végétation est dense
float dist_water = f@dist_water; // attribut précalculé
// Croissance exponentielle inverse : dense près de l'eau
float moisture = exp(-0.1 * dist_water);
float lush_bonus = exp(-0.05 * dist_water) - 0.3;
// Les 3 niveaux répondent différemment à l'humidité
float prob_tree = moisture * 0.8;
float prob_bush = moisture * 1.2; // arbustes très sensibles
float prob_grass = clamp(lush_bonus, 0, 1);
float r = rand(@ptnum);
if (r < prob_tree) i@layer = 1;
else if (r < prob_bush) i@layer = 2;
else if (r < prob_grass) i@layer = 3;
else removepoint(0, @ptnum);
La suite de Fibonacci
Popularisée en Europe par Leonardo Pisano (v. 1170-1250) dans son Liber Abaci, la suite existait déjà en Inde dès le 6e siècle, définie par une récurrence simple : F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2) → 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144... Les ratios consécutifs convergent vers φ : 5/3 = 1,667, 8/5 = 1,600, 13/8 = 1,625, 21/13 = 1,615, 34/21 = 1,619, 55/34 ≈ 1,618. Ce lien a été explicitement noté par Johannes Kepler au 17e siècle ; la formule de Binet le formalise sous la forme Fₙ = (φⁿ − (−φ)⁻ⁿ) / √5.
Applications au terrain - Octaves de Fibonacci
Plutôt que des octaves régulières (1, 2, 4, 8...), utiliser des valeurs de Fibonacci pour les fréquences de bruit crée des irrégularités imitant les vraies formations géologiques, avec une amplitude décroissant de 1/φ à chaque octave - exactement comme dans la nature.
// VEX à l'intérieur d'un Heightfield Noise - Octaves de Fibonacci
float fib[] = {1, 1, 2, 3, 5, 8, 13, 21, 34};
float phi = 1.61803398874989;
float height = 0;
float amplitude = 1.0;
for (int i = 0; i < len(fib); i++) {
float freq = fib[i] * 0.018;
height += noise(v@P * freq) * amplitude;
amplitude /= phi; // atténuation par 1/phi
}
// Ajouter une base basse fréquence avec e pour l'atténuation générale
float base = exp(-0.002 * length(set(v@P.x, 0, v@P.z)));
f@height = height * base * 120.0; // hauteur max 120m
Espacement de Fibonacci pour le LOD
// Densité LOD par distance - seuils de Fibonacci
float fib[] = {1,1,2,3,5,8,13,21,34,55};
float unit = 8.0; // mètres par unité de Fibonacci
float dist = length(v@P - v@Eye);
int lod_idx = clamp(int(dist / (unit * 3)), 0, 9);
// Probabilité inversement proportionnelle à Fibonacci
float keep_prob = 1.0 / fib[lod_idx];
if (rand(@ptnum) > keep_prob)
removepoint(0, @ptnum);
// Résultat : densité 1/1, 1/2, 1/3, 1/5, 1/8, 1/13... avec la distance
La règle des 3×3 - Une méthode originale
Après des années de création d'environnements procéduraux en véritable production, une chose devient claire : la richesse visuelle ne vient pas du nombre d'assets, mais de leur organisation stratégique. Multiplier les espèces de plantes, les types de roche ou les variantes de sol ne produit pas un environnement plus réaliste - cela produit un chaos visuel qui surcharge le moteur de rendu et fatigue l'œil. La règle des 3×3 est née de cette observation : une contrainte délibérée qui force des choix qualitatifs et garantit une cohérence visuelle à toute distance de caméra, tout en maintenant une performance optimale. (Voir aussi le traitement plus complet dans Terrains heightfield, biomes et végétation.)
| Niveau | Sélection | Exemples |
|---|---|---|
| Niveau 1 - Grande échelle | 3 éléments dominants | Grands arbres, rochers massifs, structures imposantes |
| Niveau 2 - Échelle moyenne | 3 éléments intermédiaires | Arbustes, hautes herbes, petits rochers, buissons |
| Niveau 3 - Niveau du sol | 3 éléments de sol | Mousse, galets, plantes basses, litière de feuilles, fougères |
La règle est indépendante du logiciel et s'applique de façon identique dans tous les outils : Houdini (Scatter + Copy to Points, avec des attributs pscale/orient/Cd/variant), Blender (Geometry Nodes avec distribution de points et instanciation), Terragen (Population Objects avec des rampes de densité par niveau), Gaea (exporter des masques de zone d'altitude/pente pour amorcer chaque couche), et Unity/Unreal (Foliage Painter avec un pinceau de densité par couche).
Scatter 3×3 complet intégrant les quatre nombres
// VEX - Scatter 3x3 intégrant PI, phi, e, et Fibonacci
float PI = 3.14159265358979;
float phi = 1.61803398874989;
// Distance et humidité
float dist = length(set(v@P.x, 0, v@P.z));
float moisture = exp(-0.08 * dist); // e - atténuation de densité
float slope = f@slope;
// Masque de bruit avec fréquences de Fibonacci
float n1 = noise(v@P * 0.013); // grande échelle (octaves espacées phi ci-dessous)
float n2 = noise(v@P * 0.021); // échelle moyenne (x phi)
float n3 = noise(v@P * 0.034); // échelle fine (x phi)
float mask = (n1 + n2*0.618 + n3*0.382) / 2.0;
// Assignation de niveau selon les conditions
float prob = mask * moisture;
if (slope < 15.0 && prob > 0.65) {
i@layer = 1; // Grande échelle
i@variant = int(rand(@ptnum) * 3); // 3 espèces
f@pscale = 10.0 / pow(phi, 0); // échelle phi L1
}
else if (slope < 30.0 && prob > 0.35) {
i@layer = 2; // Échelle moyenne
i@variant = int(rand(@ptnum+100) * 3);
f@pscale = 10.0 / pow(phi, 1); // échelle phi L2 = 6.18
}
else if (prob > 0.1) {
i@layer = 3; // Niveau du sol
i@variant = int(rand(@ptnum+200) * 3);
f@pscale = 10.0 / pow(phi, 2); // échelle phi L3 = 3.82
}
else removepoint(0, @ptnum);
// Orientation via l'angle d'or (PI + phi)
float golden_angle = 2.0 * PI * (1.0 - 1.0/phi);
float rot = (@ptnum * golden_angle) + noise(v@P * 0.2) * PI;
p@orient = set(0, sin(rot*0.5), 0, cos(rot*0.5)); // quaternion -> p@, pas v@
Algorithmes de distribution
Chaque motif de bruit génère un type de distribution différent, correspondant à un phénomène naturel spécifique. Utiliser le mauvais algorithme pour un niveau donné produit un résultat qui « sonne faux » immédiatement à l'œil, même sans pouvoir expliquer pourquoi.
Poisson Disk Sampling
L'algorithme de référence pour les éléments de niveau 1 qui ne doivent pas se chevaucher. Houdini l'offre nativement dans le nœud Scatter via l'option Relax Iterations ; pour un contrôle fin :
// VEX - Vérification Poisson Disk via voisinage spatial
float min_dist = 5.0; // distance minimale entre arbres (mètres)
// Chercher des voisins dans le rayon min_dist
int neighbors[] = nearpoints(0, v@P, min_dist);
// Si un voisin est plus proche que min_dist -> supprimer
if (len(neighbors) > 1)
removepoint(0, @ptnum);
// Astuce : lancer 5+ passes de relax pour un résultat optimal
DLA - Diffusion-Limited Aggregation (mousse et lichen)
Le DLA simule la croissance par diffusion : des particules effectuent une marche aléatoire jusqu'à rencontrer un cluster existant - le motif derrière la mousse sur les rochers, le lichen, et les formations coralliennes, tout ce qui « pousse » vers l'extérieur depuis un centre.
// VEX simplifié - Clustering DLA avec une gaussienne
vector center = {0, 0, 0}; // point de départ (rocher, tronc...)
float sigma = 15.0; // rayon de dispersion
// Distance gaussienne depuis le centre
float d = length(v@P - center);
float density = exp(-(d*d) / (2.0 * sigma * sigma));
// Variation angulaire pour les branches DLA
float angle = atan2(v@P.z - center.z, v@P.x - center.x);
float branch = abs(sin(angle * 5.0)) * 0.4; // 5 branches
float keep = density + branch * density;
if (rand(@ptnum) > keep) removepoint(0, @ptnum);
Pipeline complet et checklist
Les cinq outils mathématiques s'intègrent naturellement dans un pipeline d'environnement multi-logiciels : Gaea génère une heightmap avec des octaves de Fibonacci plus des masques de zone d'altitude/pente exportés ; Houdini importe la heightmap et exécute le scatter 3×3 (Poisson pour L1, bruit bleu pour L2, DLA pour L3), applique l'atténuation de densité basée sur e et l'orientation basée sur φ ; Terragen gère le rendu photoréaliste, avec des Population Objects pilotés par des rampes φ et une atmosphère volumétrique.
| Métrique | Résultat avec la méthode |
|---|---|
| Réduction du chargement d'assets | 60% vs. une approche non structurée |
| Vitesse de calcul de distribution | 90% plus rapide (Poisson vs. aléatoire brut) |
| Temps de setup par biome | 2-4h vs. 1-2 jours (approche non mathématique) |
| Cohérence entre sessions | Pipeline reproductible, paramétrique, éditable |
| Qualité visuelle | Maintenue - la contrainte des 3×3 force de meilleurs choix |
Checklist de production :
- Définir les 9 assets (3×3) avant tout scatter
- Choisir l'algorithme de bruit adapté à chaque niveau
- Utiliser les fréquences de Fibonacci pour les octaves de terrain
- Appliquer l'angle d'or (2π × (1−1/φ)) pour tout placement de végétation en surface
- Implémenter une atténuation de densité e⁻ᵏˣ avec un k différent par niveau
- LOD avec des seuils φ ou Fibonacci basés sur la distance caméra
- Valider : 9 assets max par biome, variation procédurale illimitée
π, φ, e et Fibonacci ne sont pas des abstractions réservées aux mathématiciens - ce sont des outils concrets, éprouvés en production, qui permettent de générer des environnements naturels crédibles avec une efficacité remarquable. Ils fonctionnent parce que la nature les a déjà optimisés ; le travail consiste simplement à les encoder dans Houdini. La règle des 3×3 traduit ces principes en un workflow actionnable : 9 assets bien choisis, distribués par les bons algorithmes, variant selon des constantes naturelles, produisent des biomes riches et crédibles qui résistent à l'examen le plus exigeant.