pure-noise-0.2.2.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:
--
-- @
-- import Numeric.Noise qualified as Noise
--
-- myNoise :: Noise.Seed -> Float -> Float -> Float
-- myNoise = Noise.noise2At Noise.perlin2
-- @
--
-- Compose multiple noise functions:
--
-- @
-- combined :: (RealFrac a) => Noise.Noise2 a
-- combined = (Noise.perlin2 + Noise.superSimplex2) / 2
--
-- myNoise2 :: Noise.Seed -> Float -> Float -> Float
-- myNoise2 = Noise.noise2At combined
-- @
--
-- Apply fractal Brownian motion:
--
-- @
-- fbm :: (RealFrac a) => Noise.Noise2 a
-- fbm = Noise.fractal2 Noise.defaultFractalConfig Noise.perlin2
-- @
--
-- == Advanced Features
--
-- Generate 1D noise by slicing higher-dimensional noise:
--
-- @
-- noise1d :: Noise.Noise1 Float
-- noise1d = Noise.sliceY2 0.5 Noise.perlin2
--
-- evaluate :: Float -> Float
-- evaluate = Noise.noise1At noise1d 0
-- @
--
-- Transform coordinates with 'warp':
--
-- @
-- scaledAndLayered :: Noise.Noise2 Float
-- scaledAndLayered =
-- Noise.warp (\\(x, y) -> (x * 2, y * 2)) Noise.perlin2
-- + fmap (* 0.5) Noise.perlin2
-- @
--
-- Layer independent noise with 'reseed' or 'next2':
--
-- @
-- layered :: Noise.Noise2 Float
-- layered = (Noise.perlin2 + Noise.next2 Noise.perlin2) \/ 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
superSimplex2,
superSimplex3,
-- ** 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 modifier 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.SuperSimplex qualified as SuperSimplex
import Numeric.Noise.Value qualified as Value
import Numeric.Noise.ValueCubic qualified as ValueCubic
-- | 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 SuperSimplex noise. Improved OpenSimplex variant with better visual
-- characteristics.
superSimplex2 :: (RealFrac a) => Noise2 a
superSimplex2 = SuperSimplex.noise2
{-# INLINE superSimplex2 #-}
-- | 3D SuperSimplex noise (FastNoiseLite's OpenSimplex2S, two offset rotated
-- cube grids), including its default coordinate rotation.
superSimplex3 :: (RealFrac a) => Noise3 a
superSimplex3 = SuperSimplex.noise3
{-# INLINE superSimplex3 #-}
-- | 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 #-}