pure-noise-0.3.0.0: src/Numeric/Noise.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE Strict #-}
-- |
-- Maintainer: Jeremy Nuttall <jeremy@jeremy-nuttall.com>
-- Stability : experimental
--
-- Performant noise generation with composable noise functions.
--
-- Noise functions are built on a unified 'Noise' type that abstracts over
-- the seed and coordinate parameters. 'Noise2' and 'Noise3' are convenient
-- type aliases for 2D and 3D noise. These can be composed algebraically
-- with minimal performance overhead.
--
-- Noise values are generally clamped to @[-1, 1]@, although some noise
-- functions may occasionally produce values slightly outside this range.
--
-- == Basic Usage
--
-- Generate 2D Perlin noise:
--
-- >>> noise2At perlin2 seed 23.5 (-3.2)
-- -0.5102728615076121
--
--
-- Compose multiple noise functions:
-- >>> combined = (perlin2 + smootherSimplex2) / 2
-- >>> noise2At combined seed (-5.7) (7.9)
-- 0.36250273586425386
--
-- Apply fractal Brownian motion:
--
-- >>> fractal = fractal2 defaultFractalConfig perlin2
-- >>> noise2At fractal seed 55 (-2.23)
-- 0.15904649772327042
--
-- == Advanced Features
--
-- Generate 1D noise by slicing higher-dimensional noise:
--
-- >>> sliced1d = sliceY2 0.5 perlin2
-- >>> noise1At sliced1d seed 1.3
-- 1.6628682379335485e-2
--
-- Transform coordinates with 'warp':
--
-- >>> warped = warp (\(x, y) -> (x * 2, y * 2)) perlin2 + fmap (* 0.5) perlin2
-- >>> noise2At warped seed 73.7 77.127
-- -0.24590168263203727
--
-- Layer independent noise with 'reseed' or 'next2':
--
-- >>> layered = (perlin2 + next2 perlin2) / 2
-- >>> noise2At layered seed 71 (-73.37)
-- 1.8548715411324024e-2
--
-- == Coordinate domain
--
-- Coordinates are supported on the Int32 lattice range (@|x| < 2^31@; in
-- practice 'Float' precision runs out well before that).
--
-- The OpenSimplex2\/2S family first rotates coordinates into its lattice domain,
-- which shrinks its usable range by the rotation factor — up to ~1.73x, so roughly
-- @|x| < 1.2e9@.
--
-- Outside those domains, or for non-finite inputs, results are unspecified.
--
-- This behavior mirrors FastNoiseLite, but may change in a future major version.
module Numeric.Noise (
-- * Noise
--
-- | 'Noise1', 'Noise2', and 'Noise3' are type aliases for 1D, 2D, and 3D noise
-- functions built on the unified 'Noise' type. They can be evaluated with
-- 'noise1At', 'noise2At', and 'noise3At' respectively.
--
-- 'Seed' is a 'Data.Word.Word64' value used for deterministic noise generation.
Noise,
Noise1,
Noise1',
Noise2,
Noise2',
Noise3,
Noise3',
Seed,
-- * Accessors
noise1At,
noise2At,
noise3At,
-- * Noise functions
-- ** Perlin
perlin2,
perlin3,
-- ** OpenSimplex
openSimplex2,
openSimplex3,
-- ** OpenSimplex2S
smootherSimplex2,
smootherSimplex3,
-- ** Cellular
cellular2,
cellular3,
-- *** Configuration
CellularConfig (..),
defaultCellularConfig,
CellularDistanceFn (..),
CellularResult (..),
-- ** Value
value2,
valueCubic2,
value3,
valueCubic3,
-- ** Constant fields
const2,
const3,
-- * Noise alteration
-- ** Altering values
remap,
-- ** Altering parameters
warp,
reseed,
next2,
next3,
-- ** Slicing (projecting)
sliceX2,
sliceX3,
sliceY2,
sliceY3,
sliceZ3,
-- * Fractals
--
-- | Fractal noise combines multiple octaves at different frequencies and
-- amplitudes to create natural-looking, multi-scale patterns.
--
-- For custom fractal implementations using per-octave step functions,
-- see "Numeric.Noise.Fractal".
-- ** Fractal Brownian Motion (FBM)
fractal2,
fractal3,
-- ** Fractal variants
billow2,
billow3,
ridged2,
ridged3,
pingPong2,
pingPong3,
-- ** Configuration
FractalConfig (..),
defaultFractalConfig,
PingPongStrength (..),
defaultPingPongStrength,
-- * Custom kernels
--
-- | Lift a plain @seed -> coordinates -> value@ function into a composable
-- 'Noise' value — the inverses of the accessors above.
--
-- You may use these to construct custom kernels.
mkNoise1,
mkNoise2,
mkNoise3,
-- * Math utilities
clamp,
clamp2,
clamp3,
cubicInterp,
hermiteInterp,
lerp,
quinticInterp,
) where
import Numeric.Noise.Cellular (CellularConfig, CellularDistanceFn (..), CellularResult (..), defaultCellularConfig)
import Numeric.Noise.Cellular qualified as Cellular
import Numeric.Noise.Fractal
import Numeric.Noise.Internal
import Numeric.Noise.OpenSimplex qualified as OpenSimplex
import Numeric.Noise.Perlin qualified as Perlin
import Numeric.Noise.SmootherSimplex qualified as SmootherSimplex
import Numeric.Noise.Value qualified as Value
import Numeric.Noise.ValueCubic qualified as ValueCubic
-- $setup
-- >>> seed = 1234 :: Seed
-- | 2D Cellular (Worley) noise. Configure with 'CellularConfig' to control
-- distance functions and return values.
--
-- Cellular noise creates patterns based on distances to randomly distributed
-- cell points.
cellular2 :: (RealFrac a, Floating a) => CellularConfig a -> Noise2 a
cellular2 = Cellular.noise2
{-# INLINE cellular2 #-}
-- | 3D Cellular (Worley) noise. See 'cellular2'.
cellular3 :: (RealFrac a, Floating a) => CellularConfig a -> Noise3 a
cellular3 = Cellular.noise3
{-# INLINE cellular3 #-}
-- | 2D OpenSimplex noise. Smooth gradient noise similar to Perlin but without
-- directional artifacts.
openSimplex2 :: (RealFrac a) => Noise2 a
openSimplex2 = OpenSimplex.noise2
{-# INLINE openSimplex2 #-}
-- | 3D OpenSimplex noise (FastNoiseLite's OpenSimplex2, two offset rotated
-- cube grids), including its default coordinate rotation.
openSimplex3 :: (RealFrac a) => Noise3 a
openSimplex3 = OpenSimplex.noise3
{-# INLINE openSimplex3 #-}
-- | 2D SmootherSimplex noise. Improved OpenSimplex variant with better visual
-- characteristics.
smootherSimplex2 :: (RealFrac a) => Noise2 a
smootherSimplex2 = SmootherSimplex.noise2
{-# INLINE smootherSimplex2 #-}
-- | 3D SmootherSimplex noise (FastNoiseLite's OpenSimplex2S, two offset rotated
-- cube grids), including its default coordinate rotation.
smootherSimplex3 :: (RealFrac a) => Noise3 a
smootherSimplex3 = SmootherSimplex.noise3
{-# INLINE smootherSimplex3 #-}
-- | 2D Perlin noise. Classic gradient noise algorithm.
perlin2 :: (RealFrac a) => Noise2 a
perlin2 = Perlin.noise2
{-# INLINE perlin2 #-}
-- | 3D Perlin noise. Classic gradient noise algorithm.
perlin3 :: (RealFrac a) => Noise3 a
perlin3 = Perlin.noise3
{-# INLINE perlin3 #-}
-- | 2D Value noise. Simple noise based on interpolated random values at grid points.
value2 :: (RealFrac a) => Noise2 a
value2 = Value.noise2
{-# INLINE value2 #-}
-- | 3D Value noise. Simple noise based on interpolated random values at grid points.
value3 :: (RealFrac a) => Noise3 a
value3 = Value.noise3
{-# INLINE value3 #-}
-- | 2D Value noise with cubic interpolation for smoother results.
valueCubic2 :: (RealFrac a) => Noise2 a
valueCubic2 = ValueCubic.noise2
{-# INLINE valueCubic2 #-}
-- | 3D Value noise with cubic interpolation for smoother results.
valueCubic3 :: (RealFrac a) => Noise3 a
valueCubic3 = ValueCubic.noise3
{-# INLINE valueCubic3 #-}