fractal-brownian-noise
v1.0.1
Published
Fractal Brownian Motion (fBm) noise implementation for procedural generation
Maintainers
Readme
Fractal Brownian Motion (fBm) Noise Library
A TypeScript library for generating fractal Brownian motion noise with multiple octaves, perfect for procedural:
- terrain generation,
- textures,
- and natural patterns.
Overview
Fractal Brownian Motion (fBm) combines multiple layers of noise at different scales (octaves) to create natural-looking patterns with detail at multiple levels. This technique is fundamental in procedural generation for games and simulations.
Installation
This library is designed to work with simplex-noise:
npm install simplex-noiseBasic Usage
import { createNoise2D } from "simplex-noise";
import { fbm2D } from "./index";
const noise2D = createNoise2D();
// Generate terrain height
const height = fbm2D(
x,
y,
{
octaves: 6,
lacunarity: 2.0,
gain: 0.5,
frequency: 0.01,
},
noise2D
);API Reference
fbm2D(x, y, options, noiseFunc)
Generates 2D fractal Brownian motion noise.
Parameters:
x: number- X coordinatey: number- Y coordinateoptions: FbmOptions- Configuration (optional)noiseFunc: NoiseFunction2D- 2D noise function from simplex-noise
Returns: number - Noise value between -1 and 1
fbm3D(x, y, z, options, noiseFunc)
Generates 3D fractal Brownian motion noise. Great for animated effects using time as the third dimension.
fbm4D(x, y, z, w, options, noiseFunc)
Generates 4D fractal Brownian motion noise. Useful for seamlessly looping animated textures.
Configuration Options
interface FbmOptions {
octaves?: number; // Number of noise layers (default: 4)
lacunarity?: number; // Frequency multiplier per octave (default: 2.0)
gain?: number; // Amplitude multiplier per octave (default: 0.5)
amplitude?: number; // Initial amplitude (default: 1.0)
frequency?: number; // Initial frequency (default: 1.0)
}Understanding Parameters
- Octaves: More octaves = more detail, but slower performance (typical: 4-8)
- Lacunarity: How quickly frequency increases per octave (typical: 2.0)
- Gain (Persistence): How quickly amplitude decreases per octave (typical: 0.5)
- Frequency: Scale of the noise pattern (lower = larger features)
- Amplitude: Overall strength of the noise
Advanced Functions
Ridged Multifractal
Creates sharp ridges, perfect for mountain ranges:
import { ridgedMultifractal2D } from "./index";
const mountainHeight = ridgedMultifractal2D(
x,
y,
{
octaves: 6,
lacunarity: 2.5,
gain: 0.5,
},
noise2D
);Turbulence
Creates chaotic, turbulent patterns:
import { turbulence2D } from "./index";
const chaosValue = turbulence2D(x, y, { octaves: 4 }, noise2D);Domain Warping
Warps the noise space for more organic, interesting patterns:
import { domainWarp2D } from "./index";
const warpedNoise = domainWarp2D(
x,
y,
1.5, // warp strength
{ octaves: 5 },
noise2D
);Billow Noise
Creates puffy, cloud-like patterns:
import { billow2D } from "./index";
const cloudDensity = billow2D(x, y, { octaves: 4 }, noise2D);Practical Examples
Terrain Generation
import { createNoise2D } from "simplex-noise";
import { fbm2D, ridgedMultifractal2D } from "./index";
const noise2D = createNoise2D();
function generateTerrain(x: number, y: number): number {
// Base terrain
const base = fbm2D(
x,
y,
{
octaves: 6,
frequency: 0.005,
lacunarity: 2.0,
gain: 0.5,
},
noise2D
);
// Add mountains
const mountains = ridgedMultifractal2D(
x,
y,
{
octaves: 4,
frequency: 0.003,
lacunarity: 2.5,
},
noise2D
);
// Combine
return base * 0.7 + mountains * 0.3;
}Animated Clouds
import { createNoise3D } from "simplex-noise";
import { fbm3D } from "./index";
const noise3D = createNoise3D();
function getCloudDensity(x: number, y: number, time: number): number {
return fbm3D(
x,
y,
time * 0.1,
{
octaves: 4,
frequency: 0.01,
gain: 0.6,
},
noise3D
);
}Wood Texture
import { createNoise2D } from "simplex-noise";
import { fbm2D } from "./index";
const noise2D = createNoise2D();
function woodGrain(x: number, y: number): number {
const distance = Math.sqrt(x * x + y * y);
const rings = Math.sin(distance * 0.5);
const distortion = fbm2D(x, y, { octaves: 3 }, noise2D) * 0.3;
return rings + distortion;
}Procedural Biomes
import { createNoise2D } from "simplex-noise";
import { fbm2D, domainWarp2D } from "./index";
const noise2D = createNoise2D();
function getBiome(x: number, y: number): string {
const temperature = fbm2D(
x,
y,
{
octaves: 4,
frequency: 0.002,
},
noise2D
);
const moisture = domainWarp2D(
x,
y,
2.0,
{
octaves: 3,
frequency: 0.003,
},
noise2D
);
if (temperature > 0.5 && moisture < 0) return "desert";
if (temperature < -0.3) return "tundra";
if (moisture > 0.4) return "rainforest";
return "grassland";
}Curried Functions
For convenience, you can create pre-configured noise generators:
import { createNoise2D } from "simplex-noise";
import { createFbm2D } from "./index";
// Create a reusable terrain noise generator
const terrainNoise = createFbm2D(createNoise2D(), {
octaves: 6,
lacunarity: 2.5,
gain: 0.5,
frequency: 0.01,
});
// Use it easily
const height1 = terrainNoise(100, 200);
const height2 = terrainNoise(150, 250);Performance Tips
- Cache noise generators: Create once, reuse many times
- Limit octaves: Each octave doubles computation time
- Use appropriate frequency: Scale coordinates before sampling
- Pre-generate textures: Generate noise maps at load time when possible
- Use 2D when possible: Higher dimensions are slower
Performance Comparison
| Octaves | Relative Speed | Use Case | | ------- | -------------- | --------------------- | | 1 | 1x | Simple gradients | | 2 | 2x | Basic terrain | | 4 | 4x | Detailed terrain | | 6 | 6x | Very detailed terrain | | 8 | 8x | Maximum detail |
Common Patterns
Combining Multiple Noise Types
const height =
fbm2D(x, y, { octaves: 5 }, noise2D) * 0.6 +
ridgedMultifractal2D(x, y, { octaves: 3 }, noise2D) * 0.4;Masking with Noise
const mask = (fbm2D(x, y, { octaves: 2 }, noise2D) + 1) * 0.5; // 0-1
const detail = fbm2D(x, y, { octaves: 6 }, noise2D);
const masked = detail * mask;Creating Islands
const centerX = 0,
centerY = 0;
const distance = Math.sqrt((x - centerX) ** 2 + (y - centerY) ** 2);
const gradient = Math.max(0, 1 - distance / 1000);
const height = fbm2D(x, y, { octaves: 6 }, noise2D);
const island = height * gradient;Testing
This library includes a comprehensive test suite using Vitest.
Running Tests
# Install dependencies
npm install
# Run tests once
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with UI
npm run test:ui
# Run tests with coverage
npm run test:coverageTest Coverage
The test suite covers:
- All fBm functions (2D, 3D, 4D)
- Ridged multifractal
- Turbulence
- Domain warping
- Billow noise
- Curried function creators
- Edge cases and error handling
- Statistical properties
- Performance characteristics
Writing Tests
Tests are located in src/__tests__/. To add new tests:
import { describe, it, expect } from "vitest";
import { fbm2D } from "../index";
import { createNoise2D } from "simplex-noise";
describe("My Feature", () => {
it("should work correctly", () => {
const noise2D = createNoise2D();
const result = fbm2D(10, 20, { octaves: 4 }, noise2D);
expect(result).toBeTypeOf("number");
});
});License
MIT
See Also
- simplex-noise - Base noise implementation
- The Book of Shaders - Noise
- GPU Gems - Improved Perlin Noise
