noise

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 12, 2025 License: MIT Imports: 5 Imported by: 1

README

kelindar/noise
Go Version PkgGoDev Go Report Card License Coverage

Procedural Generation Methods

This package provides noise generation and sparse point sampling algorithms for Go, focusing on speed and deterministic output. It includes both classic noise functions and advanced sparse sampling techniques for procedural generation, simulations, and spatial applications. I built this primarily with offline procedural generation in mind.

Use When:

  • ✅ Generating procedural terrain, textures, or patterns
  • ✅ Creating well-spaced point distributions for sampling or placement
  • ✅ Needing high-throughput noise generation for real-time applications
  • ✅ Requiring deterministic, reproducible random patterns

Not For:

  • ❌ Cryptographic randomness or security-sensitive applications
  • ❌ True Poisson-disk sampling (this implements SSI, which is faster but different)

Simplex Noise

Classic simplex noise for smooth procedural generation.

1D Simplex Noise
1D simplex noise pattern

2D Simplex Noise
2D simplex noise pattern

3D Simplex Noise
3D simplex noise animation

// Create a simplex noise generator
s := noise.NewSimplex(12345)

// Generate 1D, 2D, or 3D noise
value1D := s.Eval(10.5)
value2D := s.Eval(10.5, 20.3)
value3D := s.Eval(10.5, 20.3, 30.1)

Fractal Brownian Motion (fBM)

Multi-octave noise for complex patterns.

1D fBM Noise
1D fractal Brownian motion

2D fBM Noise
2D fractal Brownian motion

3D fBM Noise
3D fractal Brownian motion animation

// Create an fBM generator
fbm := noise.NewFBM(12345)

// Generate fractal noise with lacunarity=2.0, gain=0.5, octaves=4
value1D := fbm.Eval(2.0, 0.5, 4, 10.5)
value2D := fbm.Eval(2.0, 0.5, 4, 10.5, 20.3)
value3D := fbm.Eval(2.0, 0.5, 4, 10.5, 20.3, 30.1)

White Noise

Generate deterministic white noise in [-1, 1] range.

1D White Noise
1D white noise pattern

2D White Noise
2D white noise pattern

// 1D white noise
value := noise.White(12345, 10.5)

// 2D white noise
value := noise.White(12345, 10.5, 20.3)

// 3D white noise
value := noise.White(12345, 10.5, 20.3, 30.1)

// N-dimensional white noise
value := noise.White(12345, 1.0, 2.0, 3.0, 4.0, 5.0)

Basic Random Values

Generate deterministic random values based on seed and input coordinates.

const seed = uint32(12345)
const x = uint64(42) // Input coordinate/hash

// Float values in [0.0, 1.0)
f32 := noise.Float32(seed, x)
f64 := noise.Float64(seed, x)

// Integer values
i := noise.Int(seed, x)
i32 := noise.Int32(seed, x)
i64 := noise.Int64(seed, x)
u := noise.Uint(seed, x)

// Normal distribution (Box-Muller)
norm32 := noise.Norm32(seed, x)
norm64 := noise.Norm64(seed, x)

Bounded Random Values

// Random integers in [0, n)
i := noise.IntN(seed, 100, x)        // [0, 100)
i32 := noise.Int32N(seed, 50, x)     // [0, 50)
i64 := noise.Int64N(seed, 1000, x)   // [0, 1000)
u32 := noise.Uint32N(seed, 256, x)   // [0, 256)
u64 := noise.Uint64N(seed, 512, x)   // [0, 512)
u := noise.UintN(seed, 128, x)       // [0, 128)

// Random integers in [a, b] (inclusive)
i := noise.IntIn(seed, 10, 20, x)       // [10, 20]
i32 := noise.Int32In(seed, -5, 5, x)    // [-5, 5]
i64 := noise.Int64In(seed, 100, 200, x) // [100, 200]
u32 := noise.Uint32In(seed, 50, 100, x) // [50, 100]
u64 := noise.Uint64In(seed, 0, 255, x)  // [0, 255]
u := noise.UintIn(seed, 1, 10, x)       // [1, 10]

Probability Functions

// Roll dice - returns true if random value < probability
success32 := noise.Roll32(seed, 0.3, x) // 30% chance
success64 := noise.Roll64(seed, 0.75, x) // 75% chance

The package provides Simple Sequential Inhibition (SSI) algorithms for generating well-spaced point distributions. These are ideal for procedural placement, sampling, and avoiding clustering artifacts.

1D Sparse Points
1D sparse point distribution

1D Sparse Points

// Generate 1D points with minimum distance of 1.0 unit
for x := range noise.SSI1(12345, 128) {
    fmt.Printf("Point at x=%.2f\n", x)
}

// Generate integer positions with custom spacing
for ix := range noise.Sparse1(12345, 512, 8) {
    fmt.Printf("Pixel at x=%d\n", ix)
}

2D Sparse Points
2D sparse point distribution

2D Sparse Points

// Generate 2D points with minimum distance of 1.0 unit
for pt := range noise.SSI2(12345, 64, 64) {
    x, y := pt[0], pt[1]
    fmt.Printf("Point at (%.2f, %.2f)\n", x, y)
}

// Generate integer positions for pixel placement
for pt := range noise.Sparse2(12345, 512, 256, 8) {
    x, y := pt[0], pt[1]
    fmt.Printf("Pixel at (%d, %d)\n", x, y)
}

Performance

Benchmarks run on 13th Gen Intel(R) Core(TM) i7-13700K CPU. Results may vary based on hardware and environment.

name                 time/op      ops/s        allocs/op   
-------------------- ------------ ------------ ------------
simplex 1D (seq)     15.9 ns      62.9M        0           
simplex 1D (rnd)     16.0 ns      62.6M        0           
simplex 2D (seq)     12.9 ns      77.7M        0           
simplex 2D (rnd)     16.5 ns      60.7M        0           
simplex 3D (seq)     22.6 ns      44.3M        0           
simplex 3D (rnd)     28.6 ns      34.9M        0           
fbm 1D (seq)         49.1 ns      20.4M        0           
fbm 1D (rnd)         51.5 ns      19.4M        0           
fbm 2D (seq)         43.0 ns      23.3M        0           
fbm 2D (rnd)         54.9 ns      18.2M        0           
fbm 3D (seq)         71.6 ns      14.0M        0           
fbm 3D (rnd)         105.3 ns     9.5M         0           
white 1D (seq)       6.2 ns       161.6M       0           
white 1D (rnd)       6.1 ns       163.4M       0           
white 2D (seq)       8.9 ns       112.6M       0           
white 2D (rnd)       8.9 ns       112.5M       0           
white 3D (seq)       12.2 ns      81.7M        0           
white 3D (rnd)       12.2 ns      82.2M        0           
sparse 1D            620.4 ns     1.6M         1           
sparse 2D            25.9 µs      38.6K        1           
ssi 1D               5.5 µs       181.2K       1           
ssi 2D               2.2 ms       446          1           
float                3.8 ns       261.6M       0           
int n                3.8 ns       259.8M       0           
norm                 27.7 ns      36.1M        0           
int in               4.4 ns       226.4M       0           
roll                 3.8 ns       260.8M       0           

Contributing

We are open to contributions, feel free to submit a pull request and we'll review it as quickly as we can. This library is maintained by Roman Atachiants

License

This project is licensed under the MIT License.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Float32

func Float32(seed uint32, x uint64) float32

Float32 returns a deterministic float32 in [0.0, 1.0) based on x

func Float64

func Float64(seed uint32, x uint64) float64

Float64 returns a deterministic float64 in [0.0, 1.0) based on x

func Int

func Int(seed uint32, x uint64) int

Int returns a deterministic int based on x

func Int32

func Int32(seed uint32, x uint64) int32

Int32 returns a deterministic int32 based on x

func Int32In

func Int32In(seed uint32, a, b int32, x uint64) int32

Int32In returns a deterministic int32 in [a, b] (inclusive) based on x

func Int32N

func Int32N(seed uint32, n int32, x uint64) int32

Int32N returns a deterministic int32 in [0, n) based on x

func Int64

func Int64(seed uint32, x uint64) int64

Int64 returns a deterministic int64 based on x

func Int64In

func Int64In(seed uint32, a, b int64, x uint64) int64

Int64In returns a deterministic int64 in [a, b] (inclusive) based on x

func Int64N

func Int64N(seed uint32, n int64, x uint64) int64

Int64N returns a deterministic int64 in [0, n) based on x

func IntIn

func IntIn(seed uint32, a, b int, x uint64) int

IntIn returns a deterministic int in [a, b] (inclusive) based on x

func IntN

func IntN(seed uint32, n, x uint64) int

IntN returns a deterministic int in [0, n) based on x

func Norm32

func Norm32(seed uint32, x uint64) float32

Norm32 returns a deterministic normally distributed float32 based on x

func Norm64

func Norm64(seed uint32, x uint64) float64

Norm64 returns a deterministic normally distributed float64 based on x

func Roll32

func Roll32(seed uint32, probability float32, x uint64) bool

Roll32 returns true if Float32(seed, x) < probability

func Roll64

func Roll64(seed uint32, probability float64, x uint64) bool

Roll64 returns true if Float64(seed, x) < probability

func SSI1

func SSI1(seed uint32, r1 int) iter.Seq[float32]

SSI1 generates a 1D hard-core pattern as a streaming iterator. Method: Simple Sequential Inhibition on a unit lattice with one jittered candidate per integer cell in [−r1, +r1]. A candidate is accepted only if it is at least 1.0 units from all previously accepted samples. Traversal order: center-out, visiting 0, +1, −1, +2, −2, ... Deterministic for a given seed. Complexity: O(n²) with the global scan used for distance checks.

Notes:

  • Up to 3 jitter attempts per cell, at most one accepted sample per cell.
  • Produces stratified, well-spaced samples. Not a Poisson-disk generator, and no blue-noise guarantee is implied.

Example:

for x := range SSI1(12345, 128) {
    // use x
}

func SSI2

func SSI2(seed uint32, r1, r2 int) iter.Seq[[2]float32]

SSI2 generates a 2D hard-core pattern as a streaming iterator. Method: Simple Sequential Inhibition on a unit lattice with one jittered candidate per integer cell in the rectangle [−r1, +r1] × [−r2, +r2]. A candidate is accepted only if its squared distance to all accepted samples is ≥ 1.0. Cells are visited in expanding square rings, center-out. Deterministic for a given seed. Complexity: O(n²) with the global scan used for distance checks.

Notes:

  • Up to 2 jitter attempts per cell, at most one accepted sample per cell.
  • Pattern is stratified and well-spaced, not a Poisson-disk generator and no blue-noise guarantee is implied.
  • For large radii, replace the global scan with a 3×3 cell-neighborhood check to obtain O(1) acceptance time per sample.

Example:

for p := range SSI2(12345, 128, 128) {
    x, y := p[0], p[1]
    // use x,y
}

func Sparse1

func Sparse1(seed uint32, w, gap int) iter.Seq[int]

Sparse1 emits integer x positions with at least gap units between any two, streamed in a center-out order across [0, w). Method: maps the SSI1 jittered lattice samples to pixel space by scaling by gap and centering to w, then drops out-of-bounds indices. Properties:

  • Deterministic for a given seed.
  • Minimum integer spacing equals gap.
  • Empty sequence if w <= 0 or gap <= 0.

Complexity: inherits SSI1 cost; O(n²) with global checks, O(n) with neighbor map.

Example:

for ix := range Sparse1(12345, 512, 8) {
    // use ix
}

func Sparse2

func Sparse2(seed uint32, w, h, gap int) iter.Seq[[2]int]

Sparse2 emits integer (x, y) positions with at least gap units between any two, streamed in a center-out order across the rectangle [0, w) × [0, h). Method: maps the SSI2 jittered lattice samples to pixel space by scaling by gap in both axes and centering to w and h, then drops out-of-bounds indices. Properties:

  • Deterministic for a given seed.
  • Minimum integer spacing equals gap in Euclidean metric.
  • Empty sequence if w <= 0, h <= 0, or gap <= 0.

Complexity: inherits SSI2 cost; O(n²) with global checks, O(n) with neighbor map.

Example:

for p := range Sparse2(12345, 512, 256, 8) {
    x, y := p[0], p[1]
    // use x, y
}

func Uint

func Uint(seed uint32, x uint64) uint

Uint returns a deterministic uint based on x

func Uint32

func Uint32(seed uint32, x uint64) uint32

Uint32 returns a deterministic uint32 based on x

func Uint32In

func Uint32In(seed uint32, a, b uint32, x uint64) uint32

Uint32In returns a deterministic uint32 in [a, b] (inclusive) based on x

func Uint32N

func Uint32N(seed uint32, n uint32, x uint64) uint32

Uint32N returns a deterministic uint32 in [0, n) based on x

func Uint64

func Uint64(seed uint32, x uint64) uint64

Uint64 returns a deterministic uint64 based on x

func Uint64In

func Uint64In(seed uint32, a, b uint64, x uint64) uint64

Uint64In returns a deterministic uint64 in [a, b] (inclusive) based on x

func Uint64N

func Uint64N(seed uint32, n uint64, x uint64) uint64

Uint64N returns a deterministic uint64 in [0, n) based on x

func UintIn

func UintIn(seed uint32, a, b uint, x uint64) uint

UintIn returns a deterministic uint in [a, b] (inclusive) based on x

func UintN

func UintN(seed uint32, n, x uint64) uint

UintN returns a deterministic uint in [0, n) based on x

func White

func White[T Number](seed uint32, coords ...T) float32

White generates deterministic white noise in [-1, 1] range based on coordinates

Types

type FBM

type FBM struct {
	// contains filtered or unexported fields
}

FBM represents a fractal Brownian motion generator

func NewFBM

func NewFBM(seed uint32) *FBM

NewFBM creates a new FBM generator with the given seed

func (*FBM) Eval

func (f *FBM) Eval(lacunarity, gain float32, octaves int, coords ...float32) float32

Eval evaluates fractal Brownian motion at the given coordinates First 3 parameters are lacunarity, gain, octaves, followed by 1-3 coordinates

type Number

type Number interface {
	~float32 | ~float64 | uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | int | ~int8 | ~int16 | ~int32 | ~int64
}

Number constraint for generic noise functions

type Simplex

type Simplex struct {
	// contains filtered or unexported fields
}

Simplex represents a simplex noise generator with its own permutation table

func NewSimplex

func NewSimplex(seed uint32) *Simplex

NewSimplex creates a new Simplex noise generator with the given seed

func (*Simplex) Eval

func (s *Simplex) Eval(coords ...float32) float32

Eval evaluates simplex noise at the given coordinates Supports 1D, 2D, and 3D noise based on number of arguments

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL