The Beauty of Numbers

π, φ, e and Fibonacci as practical tools for procedural environments

Introduction

You know them all - their names have been familiar since school: π (Pi ≈ 3.14159), φ (Phi, the golden ratio ≈ 1.61803), e (Euler's number ≈ 2.71828). But how many of us have actually used them - not in a math exercise, but in a production pipeline, to build a convincing natural environment?

These three mathematical constants are not academic curiosities - they are algorithms nature itself has used for billions of years to optimize, distribute and structure the living world. Alongside them sits their natural companion, the Fibonacci sequence, and the 3×3 Rule - a method built over years of production work that turns these mathematical principles into a concrete, reproducible workflow in Houdini, Blender, Terragen or Gaea.

None of this requires being a coding expert - even though the examples below use Houdini's VEX Wrangle nodes. The point is a way of thinking about environment creation: in nature, chaos is not random. It is ordered by light, growth, spacing, substrate and moisture. A truly natural environment isn't designed by hand - it's generated. Mathematics as ingredients, nature as the recipe.

The central idea: these numbers aren't magic - they're efficient. Where nature took millions of years to discover them through evolution, a few lines of VEX can encode them to generate photorealistic environments in a matter of hours.

π (Pi ≈ 3.14159) - The Number of Cycles and Circles

π shows up everywhere a shape rotates, coils, or is distributed in a ring: tree growth rings, the radial arrangement of petals, ripples on water, craters, vegetation zones around a water source. Anything circular or cyclical carries π's imprint. In Houdini, it comes into play in every degree-to-radian conversion, every sinusoidal terrain curve, and above all in computing the golden angle - the most powerful tool for distributing elements without overlap.

The Golden Angle - π Meets φ

The formula golden_angle = 2π × (1 − 1/φ) ≈ 137.5° is one of the most powerful tools in environment creation. It combines π and φ to produce an angle that, repeated indefinitely, places every point without ever landing on a previous one - exactly what sunflowers, pinecones and pineapples do.

// Point Wrangle - Golden spiral distribution
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;   // max distribution radius

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));
}

Circular Distributions and Concentric Rings

For natural ring formations - vegetation around a water source, rocks around a crater, fairy-ring mushrooms - π lets you position elements precisely on concentric rings with natural variation.

// VEX - Concentric ring distribution (wetland zones)
float PI = 3.14159265358979;

// 3 rings corresponding to the 3 levels of the 3x3 rule
float rings[]  = {3.0, 8.0, 13.0};   // Fibonacci radii!
float widths[] = {1.5, 2.5, 4.0};

float dist = length(set(v@P.x, 0, v@P.z));  // distance to center

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 on the ring - variation with noise
        float angle = atan2(v@P.z, v@P.x);
        f@ring_density = abs(sin(angle * rings[r])) * 0.5 + 0.5;
    }
}

Sine Curves for Terrain and Rivers

sin(π × x) and cos(π × x) generate smooth, natural curves for river meanders, terrain waves, or periodic density variation.

// VEX - Sinusoidal density variation (vegetation wave effect)
float PI = 3.14159265358979;
float freq = 0.08;

// Natural undulation of density
f@density = 0.5 + 0.5 * sin(PI * v@P.x * freq + noise(v@P * 0.3));

// Sinusoidal river
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);  // moisture decreases away from the river

φ (Phi ≈ 1.61803) - The Golden Ratio

φ is the ratio toward which consecutive Fibonacci-term ratios converge - the proportion the human eye perceives as naturally harmonious, likely because it co-evolved with a nature that uses it everywhere: tree branching, leaf arrangement, shell proportions.

Natural structureφ mechanism
Sunflower / pineconeSpirals in Fibonacci ratios (13/21, 21/34...) for maximum density
PhyllotaxisDivergence angle ≈ 137.5° (360°/φ²) avoids mutual shading
Nautilus shellLogarithmic spiral with a factor of φ between each revolution
Tree branchingEach branch divides in ratios close to φ
A4/A3 paper ratio√φ ≈ 1.272 - the same harmonious-proportion principle

Procedural Scales Based on φ

// Instance sizes based on phi - harmonious progression
float phi = 1.61803398874989;

int layer = i@layer;  // 1, 2 or 3 (3x3 rule)

// Each level is phi times smaller than the previous one
float base_scale = 10.0;
f@pscale = base_scale / pow(phi, layer - 1);
// L1 -> 10.0,  L2 -> 6.18,  L3 -> 3.82

// Natural variation +/- 20% around the phi value
f@pscale *= fit01(rand(@ptnum), 0.8, 1.2);

LOD Based on φ

// LOD density decreasing by phi with distance
float phi = 1.61803398874989;
float dist = length(v@P - v@Eye);

// Distance thresholds as powers of 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) - The Constant of Natural Growth

e is the base of natural growth and decay. Any population, radiation, or diffusion that "grows or decays in proportion to its size" follows a law in eˣ - nature's fundamental law behind dense rainforest at the center of a clearing, vegetation thinning toward rocky areas, or biome density decreasing with altitude. The function f(x) = e⁻ᵏˣ (density falloff) exactly describes how a natural element's density decreases with distance - a large k gives rapid falloff (isolated trees), a small k gives gentle falloff (grass covering the whole terrain).

Distance-Based Density Mask

// VEX - Natural density falloff with e
// k controls the falloff speed

float dist_to_center = length(set(v@P.x, 0, v@P.z));

// Parameters per level (3x3 rule)
float k_L1 = 0.08;  // trees    - slow falloff
float k_L2 = 0.15;  // shrubs   - medium falloff
float k_L3 = 0.05;  // ground   - covers everything

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);

// Add noise to break perfect symmetry
float n = noise(v@P * 0.05);
density_L1 *= fit01(n, 0.7, 1.3);

if (rand(@ptnum) > density_L1) removepoint(0, @ptnum);

Exponential Growth - Vegetation Toward a Water Source

// The closer to the water, the denser the vegetation
float dist_water = f@dist_water;  // precomputed attribute

// Inverse exponential growth: dense near water
float moisture   = exp(-0.1 * dist_water);
float lush_bonus = exp(-0.05 * dist_water) - 0.3;

// The 3 levels respond differently to moisture
float prob_tree  = moisture * 0.8;
float prob_bush  = moisture * 1.2;       // shrubs very sensitive
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);

The Fibonacci Sequence

Popularized in Europe by Leonardo Pisano (c. 1170-1250) in his Liber Abaci, the sequence already existed in India as early as the 6th century, defined by a simple recurrence: 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... Consecutive ratios converge to φ: 5/3 = 1.667, 8/5 = 1.600, 13/8 = 1.625, 21/13 = 1.615, 34/21 = 1.619, 55/34 ≈ 1.618. This connection was explicitly noted by Johannes Kepler in the 17th century; Binet's formula formalizes it as Fₙ = (φⁿ − (−φ)⁻ⁿ) / √5.

Terrain Applications - Fibonacci Octaves

Rather than regular octaves (1, 2, 4, 8...), using Fibonacci values for noise frequencies creates irregularities mimicking real geological formations, with amplitude decreasing by 1/φ at each octave - exactly as in nature.

// VEX inside a Heightfield Noise - Fibonacci octaves
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;              // falloff by 1/phi
}

// Add a low-frequency base with e for the overall falloff
float base = exp(-0.002 * length(set(v@P.x, 0, v@P.z)));
f@height = height * base * 120.0; // 120m max height

Fibonacci Spacing for LOD

// LOD density by distance - Fibonacci thresholds
float fib[] = {1,1,2,3,5,8,13,21,34,55};
float unit  = 8.0;  // meters per Fibonacci unit

float dist    = length(v@P - v@Eye);
int   lod_idx = clamp(int(dist / (unit * 3)), 0, 9);

// Probability inversely proportional to Fibonacci
float keep_prob = 1.0 / fib[lod_idx];
if (rand(@ptnum) > keep_prob)
    removepoint(0, @ptnum);

// Result: density 1/1, 1/2, 1/3, 1/5, 1/8, 1/13... with distance

The 3×3 Rule - An Original Method

After years of creating procedural environments in real production, one thing becomes clear: visual richness doesn't come from the number of assets, but from their strategic organization. Multiplying plant species, rock types or ground variants doesn't produce a more realistic environment - it produces visual chaos that overloads the render engine and tires the eye. The 3×3 Rule was born from this observation: a deliberate constraint that forces qualitative choices and guarantees visual consistency at every camera distance, while maintaining optimal performance. (See also the fuller treatment in Heightfield Terrains, Biomes and Vegetation.)

LevelSelectionExamples
Level 1 - Grand scale3 dominant elementsLarge trees, massive rocks, imposing structures
Level 2 - Medium scale3 intermediate elementsShrubs, tall grass, small rocks, bushes
Level 3 - Ground level3 ground elementsMoss, pebbles, low plants, leaf litter, ferns
For each ecosystem, select exactly 3 elements per scale level. This 9-asset maximum, combined with procedural variation in color, scale and density, is enough to create the vast majority of natural biomes with a professional result.

The rule is software-independent and applies identically across tools: Houdini (Scatter + Copy to Points, with pscale/orient/Cd/variant attributes), Blender (Geometry Nodes with point distribution and instancing), Terragen (Population Objects with per-level density ramps), Gaea (exporting altitude/slope zone masks to seed each layer), and Unity/Unreal (Foliage Painter with a per-layer density brush).

Complete 3×3 Scatter Integrating All Four Numbers

// VEX - 3x3 scatter integrating PI, phi, e, and Fibonacci
float PI  = 3.14159265358979;
float phi = 1.61803398874989;

// Distance and moisture
float dist    = length(set(v@P.x, 0, v@P.z));
float moisture = exp(-0.08 * dist);            // e - density falloff
float slope    = f@slope;

// Noise mask with Fibonacci frequencies
float n1 = noise(v@P * 0.013);  // large scale (phi-spaced octaves below)
float n2 = noise(v@P * 0.021);  // medium scale (x phi)
float n3 = noise(v@P * 0.034);  // fine scale (x phi)
float mask = (n1 + n2*0.618 + n3*0.382) / 2.0;

// Level assignment based on conditions
float prob = mask * moisture;

if (slope < 15.0 && prob > 0.65) {
    i@layer   = 1;                             // Grand scale
    i@variant = int(rand(@ptnum) * 3);        // 3 species
    f@pscale  = 10.0 / pow(phi, 0);          // phi scale L1
}
else if (slope < 30.0 && prob > 0.35) {
    i@layer   = 2;                            // Medium scale
    i@variant = int(rand(@ptnum+100) * 3);
    f@pscale  = 10.0 / pow(phi, 1);          // phi scale L2 = 6.18
}
else if (prob > 0.1) {
    i@layer   = 3;                            // Ground level
    i@variant = int(rand(@ptnum+200) * 3);
    f@pscale  = 10.0 / pow(phi, 2);          // phi scale L3 = 3.82
}
else removepoint(0, @ptnum);

// Orient via the golden angle (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@, not v@

Distribution Algorithms

Each noise pattern generates a different type of distribution, corresponding to a specific natural phenomenon. Using the wrong algorithm for a given level produces a result that immediately looks "off" to the eye, even without being able to explain why.

Poisson Disk Sampling

The reference algorithm for Level 1 elements that must not overlap. Houdini offers it natively in the Scatter node via the Relax Iterations option; for fine control:

// VEX - Poisson Disk check via spatial neighborhood
float min_dist = 5.0;   // minimum distance between trees (meters)

// Look for neighbors within radius min_dist
int neighbors[] = nearpoints(0, v@P, min_dist);

// If a neighbor is closer than min_dist -> remove
if (len(neighbors) > 1)
    removepoint(0, @ptnum);

// Tip: run 5+ relax passes for an optimal result

DLA - Diffusion-Limited Aggregation (Moss and Lichen)

DLA simulates growth by diffusion: particles perform a random walk until they meet an existing cluster - the pattern behind moss on rocks, lichen, and coral formations, anything that "grows" outward from a center.

// Simplified VEX - DLA clustering with a Gaussian
vector center = {0, 0, 0};  // starting point (rock, trunk...)
float sigma   = 15.0;       // spread radius

// Gaussian distance from the center
float d = length(v@P - center);
float density = exp(-(d*d) / (2.0 * sigma * sigma));

// Angular variation for DLA branches
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);

Complete Pipeline and Checklist

The five mathematical tools integrate naturally into a cross-software environment pipeline: Gaea generates a heightmap with Fibonacci octaves plus exported altitude/slope zone masks; Houdini imports the heightmap and runs the 3×3 scatter (Poisson for L1, blue noise for L2, DLA for L3), applies e-based density falloff and φ-based orientation; Terragen handles photoreal rendering, with Population Objects driven by φ ramps and volumetric atmosphere.

MetricResult with the method
Asset loading reduction60% vs. an unstructured approach
Distribution computation speed90% faster (Poisson vs. raw random)
Setup time per biome2-4h vs. 1-2 days (non-mathematical approach)
Consistency across sessionsReproducible, parametric, editable pipeline
Visual qualityMaintained - the 3×3 constraint forces better choices

Production checklist:

  • Define the 9 assets (3×3) before any scatter
  • Choose the noise algorithm suited to each level
  • Use Fibonacci frequencies for terrain octaves
  • Apply the golden angle (2π × (1−1/φ)) for all on-surface vegetation placement
  • Implement e⁻ᵏˣ density falloff with a different k per level
  • LOD with φ or Fibonacci thresholds based on camera distance
  • Validate: 9 assets max per biome, unlimited procedural variation

π, φ, e and Fibonacci aren't abstractions reserved for mathematicians - they're concrete, production-tested tools that make it possible to generate convincing natural environments with remarkable efficiency. They work because nature already optimized them; the job is simply to encode them in Houdini. The 3×3 Rule translates these principles into an actionable workflow: 9 well-chosen assets, distributed by the right algorithms, varying according to natural constants, produce rich, believable biomes that hold up under the most demanding scrutiny.