' Ported to QB64 by: Phlashlite, February 20, 2022
'
' Resource: Simplex noise demystified
' Author: Stefan Gustavson, Link”ping University, Sweden (stegu@itn.liu.se), 2005-03-22
' URL: https://weber.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
'
' Resource: Working with Simplex Noise
' Author: Christian Maher
' URL: https://cmaher.github.io/posts/working-with-simplex-noise/
'
' Resource: FLRMAP - simple floormapper with diagram and explanation.
' Developer: Toshi Horie March 2001
' Based on: Floormapper Ecliptorial and Qasir's constant-z optimization explanation.
'
'
' Simplex noise is a method for constructing an n-dimensional noise function comparable to
' Perlin noise ("classic" noise) but with fewer directional artifacts and, in higher dimensions, a lower computational overhead. Ken Perlin designed the algorithm in 2001[1] to address the limitations of his classic noise function, especially in higher dimensions.
' The advantages of simplex noise over Perlin noise:
'
' - Simplex noise has a lower computational complexity and requires fewer multiplications.
' - Simplex noise scales to higher dimensions (4D, 5D and up) with much less computational
' cost, the complexity is for dimensions instead of the of classic Noise.
' - Simplex noise has no noticeable directional artifacts.
' - Simplex noise has a well-defined and continuous gradient everywhere that can be computed
' quite cheaply.
' - Simplex noise is easy to implement in hardware
'
' ~Wikipedia
' https://en.wikipedia.org/wiki/Simplex_noise#:~:text=Simplex%20noise%20is%20a%20method,dimensions%2C%20a%20lower%20computational%20overhead.
'==============================================================================
g3: 'gradient
TYPE TriBit
'data structure to hold gradient data
'______________________________________________________________________________
p: 'permutation table
DATA 151,160,137,091,090,015,131,013,201,095,096,053,194,233,007,225,140,036,103,030 DATA 069,142,008,099,037,240,021,010,023,190,006,148,247,120,234,075,000,026,197,062 DATA 094,252,219,203,117,035,011,032,057,177,033,088,237,149,056,087,174,020,125,136 DATA 171,168,068,175,074,165,071,134,139,048,027,166,077,146,158,231,083,111,229,122 DATA 060,211,133,230,220,105,092,041,055,046,245,040,244,102,143,054,065,025,063,161 DATA 001,216,080,073,209,076,132,187,208,089,018,169,200,196,135,130,116,188,159,086 DATA 164,100,109,198,173,186,003,064,052,217,226,250,124,123,005,202,038,147,118,126 DATA 255,082,085,212,207,206,059,227,047,016,058,017,182,189,028,042,223,183,170,213 DATA 119,248,152,002,044,154,163,070,221,153,101,155,167,043,172,009,129,022,039,253 DATA 019,098,108,110,079,113,224,232,178,185,112,104,218,246,097,228,251,034,242,193 DATA 238,210,144,012,191,179,162,241,081,051,145,235,249,014,239,107,049,192,214,031 DATA 181,199,106,157,184,084,204,176,115,121,050,045,127,004,150,254,138,236,205,093 DATA 222,114,067,029,024,072,243,141,128,195,078,066,215,061,156,180 DATA 151,160,137,091,090,015,131,013,201,095,096,053,194,233,007,225,140,036,103,030 DATA 069,142,008,099,037,240,021,010,023,190,006,148,247,120,234,075,000,026,197,062 DATA 094,252,219,203,117,035,011,032,057,177,033,088,237,149,056,087,174,020,125,136 DATA 171,168,068,175,074,165,071,134,139,048,027,166,077,146,158,231,083,111,229,122 DATA 060,211,133,230,220,105,092,041,055,046,245,040,244,102,143,054,065,025,063,161 DATA 001,216,080,073,209,076,132,187,208,089,018,169,200,196,135,130,116,188,159,086 DATA 164,100,109,198,173,186,003,064,052,217,226,250,124,123,005,202,038,147,118,126 DATA 255,082,085,212,207,206,059,227,047,016,058,017,182,189,028,042,223,183,170,213 DATA 119,248,152,002,044,154,163,070,221,153,101,155,167,043,172,009,129,022,039,253 DATA 019,098,108,110,079,113,224,232,178,185,112,104,218,246,097,228,251,034,242,193 DATA 238,210,144,012,191,179,162,241,081,051,145,235,249,014,239,107,049,192,214,031 DATA 181,199,106,157,184,084,204,176,115,121,050,045,127,004,150,254,138,236,205,093 DATA 222,114,067,029,024,072,243,141,128,195,078,066,215,061,156,180
'To remove the need for index wrapping, double the permutation table length
'==============================================================================
'From: FLRMAP__________________________________________________________________
CONST H
= 5 ' Height of PoV @ the plane of the "Y" axis CONST DPTH
= WDTH
' Depth of the "Z" axis CONST HLV
= -500 ' Horizontal Line between sky and GP CONST GP
= -10 ' Ground Plane
'2D simplex noise. From: "Simplex noise demystified"___________________________
'Settings for noise and brownian motion. From: "Working with Simplex Noise"____
CONST SCALE
= .02 ' Noise SCALE CONST ITERATIONS
= 5 ' Affects the noise layers (octaves) CONST PERSISTENCE
= 0.5 ' Amount each octave contributes to the noise structure CONST LOW
= 0 ' Low end of point luminance CONST HIGH
= 196 ' High end of luminance CONST SPEED
= .20 ' Cloud (scroll) speed
HFV! = -(WDTH * .5)
lut(y&) = H / (H - y&)
HF(y&) = HFV * lut(y&)
D(y&) = DPTH * lut(y&)
HL = 500
'==============================================================================
vofs = vofs + SPEED
v = vofs + D(y&)
u = HF(y&)
du = lut(y&)
'Load the texture array with noise
Texture&(u, v) = map(sumOcatave(ITERATIONS, u, v + HL, PERSISTENCE, SCALE), -1, 1, LOW, HIGH)
'Grayscale pallette
c&
= _RGB(Texture&
(u
, v
), Texture&
(u
, v
), Texture&
(u
, v
))
'Draw the screen
u = u + du
'==============================================================================
FUNCTION noise2D
(xin
, yin
) 'From: Simplex noise demystified___________________
'' Skew the input space to determine which simplex cell we're in
s = (xin + yin) * F2
t = (i& + j&) * G2
' Unskew the cell origin back to (x,y) space
BX0 = i& - t
BY0 = j& - t
' The x,y distances from the cell origin
x0 = xin - BX0
y0 = yin - BY0
' For the 2D case, the simplex shape is an equilateral triangle
' Determine which simplex we are in.
' Offsets for second (middle) corner of simplex in (i,j) coords
i1& = 1: j1& = 0
i1& = 0: j1& = 1
' A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
' a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
' c = (3-sqrt(3))/6 which is G2
x1 = x0 - i1& + G2
y1 = y0 - j1& + G2
' Offsets for last corner in (x,y) unskewed coords
x2 = x0 - 1 + G2x2
y2 = y0 - 1 + G2x2
' Work out the hashed gradient indices of the three simplex corners
gi0&
= perm
(ii&
+ perm
(jj&
)) MOD 12 gi1&
= perm
(ii&
+ i1&
+ perm
(jj&
+ j1&
)) MOD 12 gi2&
= perm
(ii&
+ 1 + perm
(jj&
+ 1)) MOD 12
' Calculate the contribution from the three corners
' First corner
t0 = .5 - x0 * x0 - y0 * y0
n0 = 0
t0 = t0 * t0
n0 = t0 * t0 * DotP2(gi0&, x0, y0)
' Second corner
t1 = .5 - x1 * x1 - y1 * y1
n1 = 0
t1 = t1 * t1
n1 = t1 * t1 * DotP2(gi1&, x1, y1)
' Third corner
t2 = .5 - x2 * x2 - y2 * y2
n2 = 0
t2 = t2 * t2
n2 = t2 * t2 * DotP2(gi2&, x2, y2)
' Add contributions from each corner to get the final noise value.
' The result is scaled to return values in the interval [-1,1].
noise2D = 70 * (n0 + n1 + n2)
' From: "Working with Simplex Noise"___________________________________________
FUNCTION sumOcatave
(iterations
, x&
, y&
, persistence
, scale
)
noise = 0
maxAmp = 0
amp = 1
freq = scale
' Add successively smaller, higher-frequency terms
noise = (noise2D(x& * freq, y& * freq) * amp) + noise
maxAmp = maxAmp + amp
amp = amp * persistence
freq = freq * 2
sumOcatave = noise
'2D DotProduct. From: Simplex noise demystified________________________________
DotP2 = grad3(g&).x * x + grad3(g&).y * y
' Map function I found or translated from somewhere.___________________________
' The Coding Train" guy on youtube, where I translated the rain code from
' explained it in one of his videos.
FUNCTION map
(value
, minRange
, maxRange
, newMinRange
, newMaxRange
) map = ((value - minRange) / (maxRange - minRange)) * (newMaxRange - newMinRange) + newMinRange