A modular, editor-integrated heightmap generation toolkit for Unity 6. Procedural noise, hydraulic erosion, splatmaps, and live preview — all in one window.
Tools > OpenHeightmap (Ctrl+Alt+H)
Assets/OpenHeightmap folder into your project.Ctrl+Alt+H).If the scene has no terrain, Apply to Terrain offers to create one. Its size comes from New Terrain in the Noise tab: with Match Size To Resolution on, width and length follow the resolution (1025 → 1024 × 1024); turn it off to set them yourself. Auto Height (on by default) sets the height as a percentage of the width (Height (% of width), 40% unless a preset sets its own) so new terrains have natural proportions; turn it off to type a height. If the scene already has a terrain, Apply to Terrain updates that one and keeps its size; the New Terrain section says so, and warns when heightmap samples would be more than 4 units apart (for example a 513 map stretched over 64,000 units), which makes terrain look soft and flat. Each new terrain gets its own TerrainData asset in Assets/OpenHeightmap Generated. Generated files are kept outside the tool folder, so updating or removing the tool never touches your terrains.
For best results, use RAW16 format throughout the pipeline:
OpenHeightmap (generate) → Export RAW16 → OpenStamper (load .raw) → Apply stamps → Export RAW16 → Unity Terrain (Import Heightmap)
RAW16 and PNG both store 16-bit height precision (65,536 levels); EXR stores full 32-bit floats. RAW16 is the format Unity's terrain Import Raw reads directly.
Perlin, Simplex, Voronoi, Worley, Value, Midpoint Displacement. Each with configurable parameters.
Full particle-based hydraulic simulation with sediment transport. Thermal erosion for slope rounding.
Colored heightmap preview with zoom, click-to-read height, a grayscale toggle (Color), a custom Gradient, and optional GPU rendering. The preview is rendered once per change, so sliders stay responsive. Batch (Noise tab) generates several seeds at once as thumbnails; click one to use it. The current heightmap is rebuilt automatically after a script recompile.
Auto-generate terrain layer weights from height + slope. Configurable biome rules with preview.
Rolling Hills, Mountain Range, Island, Canyon, Plateau, Desert, Tundra, Volcanic, River Valley, Coastal Cliffs.
Export as 16-bit grayscale PNG (no terracing). The texture importer is set to single-channel (red), linear, uncompressed.
Each generation run executes passes in strict order. Only enabled passes run.
Noise
→
Domain Warp
→
Hydraulic Erosion
→
Thermal Erosion
→
Gaussian Blur
→
Laplacian Smooth
→
Falloff
→
Normalize
→
Height Multiplier
Normalization stretches the result to fill [0, 1]. Height Multiplier is applied after it: below 1 lowers the whole terrain, above 1 raises lowlands and slopes with a smooth curve that never flattens the peaks.
Noise is sampled in a fixed reference space (512 units across the map), so the same settings give the same terrain at every resolution — a higher resolution adds detail instead of zooming out. Seed changes the terrain for every noise type.
Classic gradient noise. Produces smooth, organic undulations. Good general-purpose noise for rolling terrain. Uses improved Perlin permutation table with fade function 6t^5 - 15t^4 + 10t^3.
Gradient noise on a simplex grid instead of a square grid. Fewer directional artifacts than Perlin at high frequencies. Better performance in 2D+.
Best for: Organic terrain, mountain bases, anything Perlin does but with fewer grid-aligned artifacts.Cell-based noise that computes distances to nearest feature points. Produces cell-like patterns.
| Return Type | Effect |
|---|---|
| CellValue | Random value per cell (flat regions) |
| Distance | Distance to nearest point (bowl shapes) |
| Distance2 | Distance difference between 1st and 2nd nearest (ridge lines, crater edges) |
Variant of Voronoi with hash-based point placement (no floating point artifacts). Returns distance fields.
| Return Type | Effect |
|---|---|
| F1 | Distance to nearest point |
| F2 | Distance to second nearest |
| F2-F1 | Ridge/canyon patterns |
| F1Normalized | Inverted distance (peaks at cell centers) |
Random value at each grid vertex, interpolated with Hermite smoothing. Produces very smooth, predictable results. No gradient artifacts.
Best for: Smooth plains, gentle undulations, plateau surfaces.Fractal subdivision: starts with 4 random corners, recursively subdivides with randomized midpoints. The Roughness parameter controls how much displacement decreases per subdivision level.
Particle-based simulation. Each particle starts at a random position, flows downhill under gravity, picks up sediment (erosion) and deposits it when velocity decreases. Erosion is spread over a small brush so it carves channels rather than pits. This is the single most impactful pass for realism.
| Parameter | What It Does | Recommended Range |
|---|---|---|
| Iterations | Erosion amount, in hundreds of droplets on a 513 map (200 = 20,000). The droplet count scales with map area so results look the same at any resolution. | 100-500 |
| MaxLifetime | Max steps per particle before it dies | 20-50 |
| Inertia | How much momentum carries vs. gravity direction. Higher = smoother channels | 0.01-0.1 |
| Gravity | Acceleration downhill. Higher = deeper channels | 2-10 |
| EvaporationRate | Water loss per step. Higher = shorter rivers | 0.01-0.05 |
| DepositionRate | How fast sediment drops when velocity slows | 0.1-0.5 |
| ErosionRate | How fast terrain is carved under particles | 0.1-0.5 |
Slope-based material displacement. Material slides downhill when the slope exceeds the TalusAngle threshold. Produces natural rounding of peaks and filling of valleys.
| Parameter | What It Does |
|---|---|
| Iterations | Number of passes (10-30 typical) |
| TalusAngle | Slope threshold before material moves (0.005-0.02). Measured per 513-map pixel, so it behaves the same at every resolution. |
| C | Material transfer constant (1.0 = standard) |
Convolution-based blur using a Gaussian kernel. KernelSize must be odd (auto-corrected). Sigma controls blur spread. Multiple passes compound the effect.
Each vertex moves toward the average of its 4 neighbors by Strength factor. Good for removing high-frequency noise without losing large-scale shape.
Multiplicative mask that darkens edges. Essential for island generation.
| Type | Shape |
|---|---|
| Circular | Radial falloff from center (standard island) |
| Square | Box falloff (flat center, sharp edges) |
| Diamond | Manhattan distance falloff |
| Gaussian | Smooth bell-curve falloff (most natural) |
Power — curves the falloff. Higher = steeper drop at edges.
Offset — shifts where the falloff begins. Higher = more flat center area.
Pushes the terrain around using a second, seeded noise field. Breaks up regularity and produces organic, non-repeating geological formations. Applied before erosion. Strength is the maximum shift as a fraction of the map width (0.02 ≈ 2%); Frequency uses the same units as the noise Scale.
Auto-generate terrain layer weights from height and slope. Each biome rule defines a height range and a maximum slope in real degrees (worked out from the terrain's height-to-width ratio: the active terrain's, or the New Terrain size). Weights are smooth-stepped for natural blending. Where a spot is too steep for every rule at its height, the height match is kept rather than falling back to the first layer.
Height Weight sets how sharply height bands separate (0 = height ignored). Slope Weight sets how strictly Max Slope is enforced (0 = slope ignored, 1 = a layer fades out over 10° past its Max Slope).
| Layer | Default Height | Max Slope | Color |
|---|---|---|---|
| Water | 0 – 15% | 90° | █ Blue |
| Sand | 15 – 25% | 20° | █ Tan |
| Grass | 25 – 55% | 30° | █ Green |
| Rock | 55 – 80% | 60° | █ Brown |
| Snow | 80 – 100% | 90° | █ White |
Click Generate Splatmap in the Splatmap tab to see a color-coded preview (toggle Splat in the toolbar to switch back to the heightmap). Generating a new heightmap clears the splatmap. Apply to Terrain writes it too: it is resampled to a power-of-two alphamap (513 → 512), each splat rule gets a solid-colour TerrainLayer asset in Assets/OpenHeightmap Generated/TerrainLayers (reused on later applies). Applying again, for example after switching presets, swaps those generated layers for the current rules' colours. A layer you assigned yourself (such as a real texture) keeps its slot and is never replaced.
Each preset keeps your current Resolution and Seed, and sets the New Terrain Height (% of width) to a value that suits it, so gentle presets don't come out mountainous. You can change that slider afterwards. Presets also set the Splatmap rules: Canyon, Plateau, Desert Dunes, Tundra and Volcanic bring their own layers and colors (red rock, sand, moss, ash and so on), and the rest use the default water, sand, grass, rock and snow layers. Edit the rules freely afterwards; Reset to Defaults in the Splatmap tab goes back to the default layers.
INoiseProviderpublic interface INoiseProvider
{
string Name { get; }
float Sample(float x, float y, int seed = 0);
}
All noise algorithms implement this interface. Returns value in [-1, 1] range (except MidpointDisplacement which returns [0, 1]).
HeightmapGeneratorvar generator = new HeightmapGenerator();
var parameters = new HeightmapGeneratorParameters { ... };
HeightmapData result = generator.Generate(parameters);
Main entry point. Orchestrates the full pipeline from noise to normalized output. Set generator.Progress = (stage, progress) => { ... } to receive progress updates.
HeightmapDataHeightmapData hm = new HeightmapData(513);
float h = hm.GetHeight(x, y);
float hBilinear = hm.GetHeightBilinear(u, v); // 0-1 UV coordinates
float[] flat = hm.ToFlatArray();
HeightmapData clone = hm.Clone();
Core data wrapper. Use GetHeightBilinear for smooth UV-based sampling.
HeightmapExporterHeightmapExporter.Export(heightmap, "/path/to/output.png", ExportFormat.PNG);
HeightmapExporter.Export(heightmap, "/path/to/output.raw", ExportFormat.RAW16);
Writes PNG (16-bit grayscale), RAW16 or EXR. Paths normally come from a save dialog, which already asks before overwriting; pass confirmOverwrite: true to ask again. Auto-configures the texture importer when saving inside the project.
TerrainApplierstring status = TerrainApplier.Apply(heightmap, new NewTerrainSettings(), "Assets/MyTerrains", "My Terrain");
Writes a heightmap (and optional splatmap) to the active terrain, or creates a new one. Used by both OpenHeightmap and OpenStamper. Call it outside OnGUI (for example from EditorApplication.delayCall) because it can show dialogs.
Assets/OpenHeightmap/
├── Documentation/
│ └── Index.html ← this file
├── Editor/
│ ├── OpenHeightmapWindow.cs Main EditorWindow (6 tabs + preview)
│ ├── PreviewRenderer.cs CPU / GPU preview (rendered once per change)
│ ├── HeightmapExporter.cs PNG / RAW16 / EXR export
│ ├── TerrainApplier.cs Apply to Terrain (shared with OpenStamper)
│ ├── OpenHeightmap.Editor.asmdef
│ └── Presets/
│ └── TerrainPresets.cs 10 terrain presets
├── Runtime/
│ ├── HeightmapData.cs Core float[,] wrapper
│ ├── HeightmapGenerator.cs Pipeline orchestrator
│ ├── OpenHeightmap.Runtime.asmdef
│ ├── Noise/
│ │ ├── INoiseProvider.cs Interface
│ │ ├── PerlinNoise.cs
│ │ ├── SimplexNoise.cs
│ │ ├── VoronoiNoise.cs
│ │ ├── WorleyNoise.cs
│ │ ├── ValueNoise.cs
│ │ └── MidpointDisplacement.cs
│ ├── Erosion/
│ │ ├── HydraulicErosion.cs
│ │ └── ThermalErosion.cs
│ ├── Filters/
│ │ ├── GaussianBlur.cs
│ │ ├── LaplacianSmooth.cs
│ │ ├── FalloffGenerator.cs
│ │ └── DomainWarping.cs
│ ├── Sampling/
│ │ ├── PoissonDiskSampler.cs
│ │ └── CellularAutomata.cs
│ └── Splat/
│ └── SplatmapGenerator.cs
└── Shaders/
├── PreviewCompute.compute GPU heightmap-to-color
└── PreviewShader.shader URP preview material
OpenHeightmap has a companion tool called OpenStamper for stamp-based terrain compositing. OpenStamper lets you layer procedural features (craters, mountains, ridges, rivers, etc.) onto existing heightmaps using 8 blend modes.
OpenStamper depends on OpenHeightmap — it uses HeightmapData, HeightmapExporter, and ExportFormat at both runtime and editor level. Install this asset first before adding OpenStamper.
Recommended pipeline: Generate in OpenHeightmap → Export RAW16 → Load into OpenStamper → Stamp → Export RAW16 → Import to Unity Terrain.
Open via Tools > OpenStamper (Ctrl+Alt+S).