pure-noise-0.2.1.1: src/Numeric/Noise/SuperSimplex.hs
{-# LANGUAGE Strict #-}
-- |
-- Maintainer: Jeremy Nuttall <jeremy@jeremy-nuttall.com>
-- Stability: experimental
--
-- This module implements a variation of OpenSimplex2 noise derived from FastNoiseLite.
-- See openSimplex2S
module Numeric.Noise.SuperSimplex (
-- * 2D Noise
noise2,
noise2Base,
) where
import Data.Bits
import Numeric.Noise.Internal
import Numeric.Noise.Internal.Math
noise2 :: (RealFrac a) => Noise2 a
noise2 = mkNoise2 noise2Base
{-# INLINE noise2 #-}
noise2Base :: (RealFrac a) => Seed -> a -> a -> a
noise2Base seed xo yo =
let f2 = 0.5 * (sqrt3 - 1)
to = (xo + yo) * f2
x = xo + to
y = yo + to
fx = floor x
fy = floor y
xi = x - fromIntegral @Hash fx
yi = y - fromIntegral @Hash fy
i = fx * primeX
j = fy * primeY
i1 = i + primeX
j1 = j + primeY
t = (xi + yi) * g2
x0 = xi - t
y0 = yi - t
a0 = (2 / 3) - x0 * x0 - y0 * y0
v0 = (a0 * a0) * (a0 * a0) * gradCoord2 seed i j x0 y0
v1 =
let g2t = 1 - 2 * g2
a1 =
(2 * g2t * (1 / g2 - 2)) * t
+ ((-2 * g2t * g2t) + a0)
x1 = x0 - g2t
y1 = y0 - g2t
in (a1 * a1) * (a1 * a1) * gradCoord2 seed i1 j1 x1 y1
xmyi = xi - yi
~vgx
| xi + xmyi > 1 =
let ~x2 = x0 + (3 * g2 - 2)
~y2 = y0 + (3 * g2 - 1)
~a2 = (2 / 3) - x2 * x2 - y2 * y2
in attenuate a2 seed (i + (primeX `shiftL` 1)) (j + primeY) x2 y2
| otherwise =
let ~x2 = x0 + g2
~y2 = y0 + (g2 - 1)
~a2 = (2 / 3) - x2 * x2 - y2 * y2
in attenuate a2 seed i (j + primeY) x2 y2
~vgy
| yi - xmyi > 1 =
let ~x3 = x0 + (3 * g2 - 1)
~y3 = y0 + (3 * g2 - 2)
~a3 = (2 / 3) - x3 * x3 - y3 * y3
in attenuate a3 seed (i + primeX) (j + (primeY `shiftL` 1)) x3 y3
| otherwise =
let ~x3 = x0 + (g2 - 1)
~y3 = y0 + g2
~a3 = (2 / 3) - x3 * x3 - y3 * y3
in attenuate a3 seed (i + primeX) j x3 y3
~vlx
| xi + xmyi < 0 =
let ~x2 = x0 + (1 - g2)
~y2 = y0 - g2
~a2 = (2 / 3) - x2 * x2 - y2 * y2
in attenuate a2 seed (i - primeX) j x2 y2
| otherwise =
let ~x2 = x0 + (g2 - 1)
~y2 = y0 + g2
~a2 = (2 / 3) - x2 * x2 - y2 * y2
in attenuate a2 seed (i + primeX) j x2 y2
~vly
| yi < xmyi =
let ~x2 = x0 - g2
~y2 = y0 - (g2 - 1)
~a2 = (2 / 3) - x2 * x2 - y2 * y2
in attenuate a2 seed i (j - primeY) x2 y2
| otherwise =
let ~x2 = x0 + g2
~y2 = y0 + (g2 - 1)
~a2 = (2 / 3) - x2 * x2 - y2 * y2
in attenuate a2 seed i (j + primeY) x2 y2
v2
| t > g2 = vgx + vgy
| otherwise = vlx + vly
in normalize $ v0 + v1 + v2
{-# INLINE [2] noise2Base #-}
attenuate :: (RealFrac a) => a -> Seed -> Hash -> Hash -> a -> a -> a
attenuate !vi !seed !i !j !x !y =
let !v = max 0 vi
in (v * v) * (v * v) * gradCoord2 seed i j x y
{-# INLINE attenuate #-}
normalize :: (RealFrac a) => a -> a
normalize = (18.24196194486065 *)
{-# INLINE normalize #-}