Skip to content

Noise API

The noise module provides deterministic scalar noise functions for 1D, 2D, and 3D coordinates.

Core Function Type

typedef float (*GrimoireNoiseFunction)(float x, float y, float z, hash_t seed);

This function type is used by fractal combiners to compose multiple octaves over a selected base noise.

Coordinate Conventions

  • 1D functions use x; y and z are ignored.
  • 2D functions use x and y; z is ignored.
  • 3D functions use all coordinates.
  • seed ensures deterministic output for identical input tuples.

Value Noise

Sharp Value Noise

GRIMOIRE_API float Grimoire_ValueSharp1D(float x, float y, float z, hash_t seed);
GRIMOIRE_API float Grimoire_ValueSharp2D(float x, float y, float z, hash_t seed);
GRIMOIRE_API float Grimoire_ValueSharp3D(float x, float y, float z, hash_t seed);

Characteristics:

  • Abrupt transitions between cell values.
  • Useful for blocky, pixel-like, or stepped procedural patterns.
  • Output is documented as noise in approximately [0.0, 1.0].

Smooth Value Noise

GRIMOIRE_API float Grimoire_ValueSmooth1D(float x, float y, float z, hash_t seed);
GRIMOIRE_API float Grimoire_ValueSmooth2D(float x, float y, float z, hash_t seed);
GRIMOIRE_API float Grimoire_ValueSmooth3D(float x, float y, float z, hash_t seed);

Characteristics:

  • Interpolated transitions between lattice values.
  • Better for soft gradients (height fields, texture masks, blend maps).
  • Output is documented as noise in approximately [0.0, 1.0].

Perlin Noise

GRIMOIRE_API float Grimoire_Perlin1D(float x, float y, float z, hash_t seed);
GRIMOIRE_API float Grimoire_Perlin2D(float x, float y, float z, hash_t seed);
GRIMOIRE_API float Grimoire_Perlin3D(float x, float y, float z, hash_t seed);

Characteristics:

  • Gradient-based smooth noise.
  • Natural-looking variation for terrain, clouds, and procedural motion.
  • Deterministic with fixed seed and coordinates.

Fractal Combiners

GRIMOIRE_API float Grimoire_Fbm(
    GrimoireNoiseFunction noiseFunc,
    float x,
    float y,
    float z,
    hash_t seed,
    const GrimoireFractalSettings* settings);

GRIMOIRE_API float Grimoire_Billow(
    GrimoireNoiseFunction noiseFunc,
    float x,
    float y,
    float z,
    hash_t seed,
    const GrimoireFractalSettings* settings);
  • Grimoire_Fbm: additive octave accumulation.
  • Grimoire_Billow: additive octave accumulation with per-octave absolute-value shaping for softer cloud-like ridges.

GrimoireFractalSettings

typedef struct GrimoireFractalSettings
{
    float frequency;
    uint32_t octaves;
    float lacunarity;
    float persistence;
    bool staticSeed;
} GrimoireFractalSettings;

Parameter semantics:

  • frequency: starting sampling frequency for octave 0.
  • octaves: number of layers to sum.
  • lacunarity: frequency multiplier between octaves.
  • persistence: amplitude multiplier between octaves.
  • staticSeed: when true, uses a stable seed pattern across octaves.

Practical tuning ranges:

  • frequency: 0.005 to 0.05 for large-scale terrain-like features.
  • octaves: 3 to 8 for most game/runtime use.
  • lacunarity: around 2.0 as a baseline.
  • persistence: 0.35 to 0.65 for balanced roughness.

If staticSeed is false, each octave uses seed + octaveIndex.

Determinism Rules

Given the same:

  • function (ValueSharp, ValueSmooth, Perlin, Fbm, Billow)
  • coordinates
  • seed
  • fractal settings

the output is reproducible.

Example: 2D Fractal Height Sample

#include <grimoire-pcg/noise.h>

float sample_height(float x, float y)
{
    GrimoireFractalSettings s;
    s.frequency = 0.02f;
    s.octaves = 5;
    s.lacunarity = 2.0f;
    s.persistence = 0.5f;
    s.staticSeed = true;

    return Grimoire_Fbm(Grimoire_Perlin2D, x, y, 0.0f, 1337, &s);
}

Example: Animated Cloud Slice Using 3D Noise

#include <grimoire-pcg/noise.h>

float cloud_density(float x, float y, float timeSeconds, hash_t seed)
{
    GrimoireFractalSettings s;
    s.frequency = 0.015f;
    s.octaves = 5;
    s.lacunarity = 2.0f;
    s.persistence = 0.5f;
    s.staticSeed = true;

    /* Treat time as Z to animate through a stable 3D field. */
    float z = timeSeconds * 0.08f;
    return Grimoire_Billow(Grimoire_Perlin3D, x, y, z, seed, &s);
}

Implementation Considerations

  • Ensure settings points to a valid GrimoireFractalSettings instance.
  • In 1D and 2D variants, z is accepted for signature consistency but not used.
  • For higher octave counts, profile runtime cost against target performance budgets.
  • Treat outputs as deterministic procedural values, not cryptographic entropy.