Heightfield Terrains, Biomes and Vegetation

Sculpting, eroding, masking and populating a landscape - non-destructively

A Complete Procedural Terrain System

Houdini's Heightfield system is one of the most capable terrain-creation workflows available in any VFX package. Introduced in Houdini 16.5, it's built on a volumetric heightmap representation, processed through dedicated SOP nodes that let you sculpt, erode, mask and populate a terrain entirely procedurally and non-destructively.

Unlike approaches where a terrain is just a deformed mesh, Houdini's Heightfield is a 2.5D volume: every cell of the grid holds a height value plus a set of layers that can store extra information - masks in particular. Those masks are the key to the entire logic behind vegetation, biome and material placement.

The procedural approach means you can tweak an upstream parameter - the frequency of the noise generating the mountains, say - and watch the whole terrain, its masks, biomes and vegetation recalculate automatically. That non-destructiveness is what makes the Heightfield workflow so valuable in production.

Generating and Sculpting the Terrain

The Heightfield Node

Everything starts with the Heightfield SOP, which creates the base grid. Its core parameters define the whole scene:

  • Grid Spacing - the size of each cell in Houdini units. A value of 1.0 gives a one-meter cell, a good starting point for human-scale terrain.
  • Size X / Size Y - the terrain's overall dimensions. A 1024×1024-unit terrain with a Grid Spacing of 1.0 gives a 1024×1024-cell resolution.
  • Height Scale - the vertical scale factor, letting you amplify or flatten the overall relief without touching downstream nodes.
  • Sampling - the heightmap's effective resolution. Higher resolution means more detail but heavier memory use.

Noise-Generation Nodes

Heightfield Noise is the main relief generator, applying different types of mathematical noise to the heightmap to create natural shapes:

  • Perlin Noise - the classic. Soft, organic shapes, ideal for rolling plains and gentle hills.
  • Simplex Noise - more natural than Perlin, with less visible regularity. Widely used for mountains.
  • Billowy Noise - creates puffy shapes, perfect for sand dunes or cloud-like terrain.
  • Ridged Noise - generates sharp ridges and pronounced valleys - the natural choice for mountain ranges.
  • Distortion - warps the noise itself to create more organic, less regular shapes.

The key to a convincing terrain is layering several Heightfield Noise nodes at different frequencies and amplitudes: low-frequency noise for the overall shape (the big mountains), mid-frequency for secondary hills, and high-frequency for surface detail (roughness, micro-relief).

Sculpting and Erosion Nodes

  • Heightfield Erode - the most powerful node for giving a terrain a natural look. It simulates hydraulic (water) and thermal (gravity) erosion by calculating sediment displacement across the surface, and automatically generates several useful masks along the way: Flow (drainage areas), Sediment (deposits), Curvature.
  • Heightfield Blur - smooths selected areas. Useful for softening overly sharp transitions or simulating sedimentary plains.
  • Heightfield Distort by Layer - deforms the heightmap using another layer as a displacement vector, creating complex shapes impossible to get from noise alone.
  • Heightfield Terrace - generates horizontal terraces, characteristic of certain rock types or terraced farmland.
  • Heightfield Project - projects an external mask or image onto the terrain to import a specific shape (a drawn coastline, an island from a map, etc.).

Feature Masks: Defining Terrain Zones

Masks are the central concept behind all vegetation and biome logic in the Heightfield workflow. A mask is an extra heightmap layer whose values range from 0 to 1, representing the intensity of a geographic feature. These masks then drive plant placement, material choice, and biome definition.

Heightfield Mask by Feature

This is the main tool for generating masks from the terrain's geometric characteristics, analyzing the heightmap's shape according to the chosen criterion:

  • Height - a mask based on altitude. High areas approach 1, low areas approach 0. Used to define snow on peaks, alpine vegetation, tundra zones. Parameters: Min Height, Max Height.
  • Slope - a mask based on surface incline. A 0° slope (flat) gives 0, a 90° slope (vertical cliff) gives 1. Essential for telling cliffs (no vegetation) apart from plains (dense vegetation) - the typical cutoff for excluding cliffs is beyond 35°.
  • Curvature - a mask based on surface convexity or concavity. Convex areas (ridges, domes) and concave areas (valleys, basins) can be masked separately - particularly useful for placing moisture and dense vegetation in hollows, and drought-tolerant plants on exposed ridges.
  • Flow - generated by Heightfield Erode, this mask marks where water naturally drains. Ideal for placing riparian vegetation (riverbank plants), wetlands and marshes.
  • Sediment - also from erosion, it shows where sediment settles - flat, low-lying areas. Corresponds to alluvium, riverbanks and floodplains.
  • Occlusion - computes areas tucked into hollows with little exposure to skylight, simulating relative humidity: occluded areas retain more moisture and favor different vegetation than exposed areas.

Heightfield Mask by Occlusion

This dedicated node computes an ambient-occlusion mask directly on the terrain, simulating the proportion of visible sky at every point: a value of 1 means the point is fully exposed (a summit, a ridge), 0 means it's entirely in a hollow (valley floor, gorge). This is one of the most useful masks for building believable biomes, since it correlates directly with real sunlight and moisture.

Combining Masks

The real power of masks comes from combining them. Heightfield Layer is the basic tool for combining several masks via boolean or math operations - addition, subtraction, multiplication, minimum, maximum. A temperate-forest mask, for instance, might combine:

forest = (low_altitude) × (gentle_slope) × (moderate_flow)

In practice, that translates into a chain of Heightfield Layer nodes successively multiplying masks. Heightfield Remap lets you adjust the transition curves (falloff) between zones for smooth, natural transitions rather than hard cuts.

The Heightfield Paint Node

When procedural generation isn't enough, Heightfield Paint lets you manually paint masks directly in the viewport - to locally correct an automatically generated mask, carve out specific exclusion zones, or artistically guide the placement of certain elements. It's the finishing tool that rounds out the procedural approach.

Biomes: Organizing Vegetation by Zone

A biome is a geographic zone defined by specific environmental conditions - altitude, slope, moisture, sunlight - that determine what vegetation grows there. In Houdini, biomes aren't a native software concept as such, but a methodology the artist builds by combining masks to define exclusive or graduated zones of membership.

Defining Biomes by Combining Masks

The recommended approach is to define each biome as the intersection of several characteristic masks. A typical setup for a temperate mountain terrain:

  • Alpine biome (summits) - altitude > 80% + moderate slope. Low vegetation, rocks, snow. Almost no large trees.
  • Conifer forest - altitude 50-80% + slope < 40°. Spruce, fir, Scots pine. Fern and blueberry undergrowth.
  • Mixed forest - altitude 20-50% + slope < 35° + moderate occlusion. Broadleaf/conifer mix, rich undergrowth.
  • Plain / meadow - low altitude + near-zero slope + high sediment. Tall grass, low shrubs, wildflowers.
  • Riparian - high flow + low altitude. Willows, alders, aquatic plants, reeds.
  • Cliff / scree - slope > 40°. No vegetation, or rock-dwelling plants (lichen, cliff plants).

These biomes shouldn't have hard edges. Using Heightfield Remap on each mask creates gradual transitions and realistic ecotones (transition zones between biomes) - in nature, forests don't stop at a precise altitude, they fade out over dozens of meters.

Visualizing and Testing Biomes

Before running vegetation scatter, it's worth visualizing the biome masks directly on the terrain. Heightfield Visualize displays any heightfield layer as color in the viewport, letting you confirm the biome zones make geographic sense before placing any vegetation.

The 3×3 Rule: Structuring Plant Diversity

The 3×3 rule is a planting methodology that guarantees both visual diversity and ecological coherence in a natural environment. The principle is simple: for each biome, define 3 species types, each in 3 sizes (small, medium, large). That produces 9 variations per biome - enough to avoid visual repetition while staying manageable in production.

The Three Types

  • Type 1 - Dominants (canopy) - the tall trees or shrubs that define the biome's silhouette and volume, the most visible elements from a distance. Example for a temperate forest: oak, beech, spruce. They occupy 20-30% of the surface but represent 80% of the visual mass.
  • Type 2 - Intermediates (shrub layer) - shrubs, small trees and mid-sized plants that fill the space between dominants and ground, creating visual transition and depth. Example: hazel, privet, juniper, tree fern.
  • Type 3 - Ground cover (low layer) - ground plants, grasses, moss, flowers, mushrooms that cover the soil and fill empty spaces - the most numerous by density but the smallest. Example: ferns, grasses, brambles, blueberries, moss.

The Three Sizes

For each type, prepare three size variants of the same 3D model or species, obtained by scaling or by distinct models:

  • Small (S) - 30-60% of reference size. Young plants, stunted individuals, or naturally dwarf species. High density.
  • Medium (M) - 100% of reference size. The standard adult individual. Moderate density.
  • Large (L) - 130-200% of reference size. Exceptional individuals, old specimens. Low density, high visual impact.

Size variation shouldn't be purely a matter of scale: ideally each size also varies in shape (more drooping branches for old trees, a slimmer silhouette for young ones) and texture (denser, darker foliage for adults). In Houdini, that means three separate assets in the library, instanced according to the size mask.

Worked Example: 3×3 Temperate Forest

  • Oak S/M/L - thin trunk / medium trunk / wide trunk with spreading crown. Scattered on the mixed-forest mask, low density.
  • Hazel S/M/L - compact shrub / spreading shrub / dense bush. Scattered on the shrub layer, medium density.
  • Bracken fern S/M/L - small tuft / medium tuft / large fern. Scattered on the forest floor, high density.

This 3×3 grid gives 9 independent scatter passes, each with its own density, mask and orientation parameters. Placement order matters: start with the large dominants, then intermediates, then ground cover - each layer can use the presence mask of the previous layers to adapt to it (ferns grow in the shade of oaks, not in full sun).

Heightfield Scatter: Placing Vegetation

Heightfield Scatter places elements across a Heightfield's surface, generating a point cloud distributed according to the density and masking parameters you define. These points then feed a Copy to Points or Instance node to place the actual 3D vegetation models.

Core Parameters

  • Count - total number of points to generate. Note this is absolute, not a relative density - adjust it based on terrain size.
  • Global Density - a global density multiplier, letting you quickly adjust the whole scatter without touching Count.
  • Seed - the random seed for the distribution. Changing the seed gives a different distribution with the same parameters - essential for getting variation between two similar scatters.
  • Relax Iterations - applies a Poisson relaxation algorithm to avoid overly clustered points, giving a more natural, less random-looking distribution.
  • Layer Mask - the heightfield layer used as the density mask. Areas with a value of 1 get maximum density, areas at 0 get no points.

Scatter Driven by Biome Masks

The connection between biome masks and Heightfield Scatter happens through the Layer Mask parameter. For each biome and vegetation type, you create a separate Heightfield Scatter node using the matching mask. Following the 3×3 example for a temperate forest:

Scatter 1: Oak S      | Mask: mixed_forest × low_altitude | Count: 200  | Seed: 1
Scatter 2: Oak M      | Mask: mixed_forest × low_altitude | Count: 150  | Seed: 2
Scatter 3: Oak L      | Mask: mixed_forest × low_altitude | Count: 50   | Seed: 3
Scatter 4: Hazel S    | Mask: mixed_forest × shade        | Count: 500  | Seed: 4
Scatter 5: Hazel M    | Mask: mixed_forest × shade        | Count: 350  | Seed: 5
Scatter 6: Hazel L    | Mask: mixed_forest                | Count: 150  | Seed: 6
Scatter 7: Fern S     | Mask: forest_floor × occlusion     | Count: 2000 | Seed: 7
Scatter 8: Fern M     | Mask: forest_floor × occlusion     | Count: 1500 | Seed: 8
Scatter 9: Fern L     | Mask: forest_floor                 | Count: 800  | Seed: 9

Each Heightfield Scatter produces a point cloud with attributes (position, terrain normal, local slope) that can be used to orient vegetation instances - plants naturally align with the terrain normal through the auto-generated N attribute.

Automatic Heightfield Scatter Attributes

  • P (Position) - the 3D position of the point on the terrain surface.
  • N (Normal) - the surface normal at the point, for aligning instances with the ground.
  • up - the world vertical vector, useful combined with N to control orientation.
  • height - the altitude value at the point, for varying instance parameters by elevation.
  • slope - the slope value at the point, which can modulate instance size or orientation.

Instancing and Model Variation

Once points are generated, use Copy to Points (for complete geometry) or Instance (for lightweight GPU instances) to place the 3D models. To apply the 3×3 rule, a single Heightfield Scatter can drive random asset variation through an Attribute Wrangle:

// Randomly assign one of 3 sizes
i@variant = int(rand(@ptnum) * 3);  // 0, 1 or 2

// Random scale variation within each size
float scales[] = {0.6, 1.0, 1.5};
f@scale = scales[@variant] * fit01(rand(@ptnum + 42), 0.85, 1.15);

Copy to Points then reads the variant attribute to pick the matching asset from a list, and the scale attribute to apply scaling - producing natural variation without multiplying the number of nodes in the network.

Network Organization and Performance

A full Heightfield network can quickly get complex with multiple mask layers and scatter passes. Rigorous organization is essential to keep things readable and easy to modify.

Recommended Structure in Functional Blocks

  • Base Terrain block - Heightfield + Heightfield Noise nodes (low, mid and high frequency). Output named OUT_terrain_base.
  • Erosion block - Heightfield Erode with hydraulic and thermal erosion parameters. Output OUT_terrain_eroded, generating the Flow and Sediment layers.
  • Masks block - all Heightfield Mask by Feature nodes and their combinations, one Null per final mask, explicitly named: MASK_altitude, MASK_slope, MASK_flow, MASK_forest, MASK_alpine, etc.
  • Biomes block - combining masks to define each biome. Outputs named BIOME_forest, BIOME_meadow, BIOME_alpine, etc.
  • Scatter block - the 9 Heightfield Scatter passes (one per 3×3 cell), followed by a Merge to consolidate all points.
  • Instances block - Copy to Points or Instance on the merged point cloud. Final output OUT_vegetation.

Performance Tips

  • Work at low resolution first - start with a large Grid Spacing (low resolution) to set up mask and scatter logic; raise resolution only for the final render.
  • Toggle the Display flag selectively - showing terrain and instances at once can be heavy; work on masks with just the terrain shown, then enable instances for checks.
  • Limit Relax Iterations - Poisson relaxation is expensive; 2-3 iterations is usually enough. Reserve high values for sparse scatters where regularity matters.
  • Precompute heavy masks - occlusion and erosion are costly to calculate. Use Heightfield File to cache them once the result looks right, and load the cache for the rest of the pipeline.

Export and Pipeline Integration

Exporting the Terrain

  • Heightmap PNG/EXR - via Heightfield Output, exporting the heightmap as a 16- or 32-bit image. A universal format compatible with Unity, Unreal, and most engines.
  • Houdini mesh (bgeo/obj/FBX) - via Convert Height Field (SOP), converting the heightfield into standard polygon geometry for Houdini materials and rendering with Karma or Mantra.
  • USD - a full terrain + vegetation scene export via the Solaris workflow - the industry standard for complex pipelines.

Exporting Masks for Texturing

The masks generated for vegetation are equally valuable for terrain texturing - export them as textures for splat mapping (blending textures according to masks) in the render engine:

  • Rock texture - on the strong-slope mask.
  • Snow texture - on the high-altitude mask.
  • Grass texture - on the plain/sediment mask.
  • Wet-earth texture - on the flow and occlusion masks.

Complementary Tools and Resources

  • Houdini SideFX Labs - the free Labs package adds many extra terrain nodes, including procedural road generation, rivers, and advanced biome population. Highly recommended.
  • Gaea - dedicated terrain-generation software with a very advanced erosion workflow; terrains built in Gaea can be imported into Houdini as heightmaps to apply the vegetation logic above.
  • World Creator - a real-time alternative to Gaea with a very fast GPU viewport; a good complement to Houdini for the artistic sculpting phase.

Documentation