Last active
March 1, 2019 20:33
-
-
Save hperantunes/5d8d3d0e6299d2124009325ed5fdcc9d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 1D noise generator function. | |
* Inspired by https://codepen.io/Tobsta/post/procedural-generation-part-1-1d-perlin-noise | |
* | |
* @param {string} seed Initializes the pseudorandom number generator (default empty) | |
* @param {number} width Total number of points in the generated noise line (default 1) | |
* @param {number} amplitude Height of the wave (default 128) | |
* @param {number} wavelength Distance between the peaks of each wave (default 128) | |
* @param {number} octaves How many noise lines will be combined together (default 8) | |
* @param {number} divisor Number by witch each noise line will be divided (default 2) | |
* @param {number} offset Proportional offset applied to the amplitude (default -0.5) | |
* @return An array of points in a line | |
* @customfunction | |
*/ | |
function NOISE(seed, width, amplitude, wavelength, octaves, divisor, offset) { | |
var seed = xmur3(seed !== undefined ? seed.toString() : ""), | |
width = width !== undefined ? width : 1 | |
amp = amplitude !== undefined ? amplitude : 128, | |
wl = wavelength !== undefined ? wavelength : 128, | |
octaves = octaves !== undefined ? octaves : 8, | |
divisor = divisor !== undefined ? divisor : 2, | |
offset = offset !== undefined ? offset : -0.5; | |
var prng = sfc32(seed, offset); | |
var noise = generateNoise(prng, amp, wl, octaves, divisor, width); | |
return combineNoise(noise); | |
} | |
// hash function | |
function xmur3(str) { | |
for(var i = 0, h = 1779033703 ^ str.length; i < str.length; i++) { | |
h = (h ^ str.charCodeAt(i)) * 3432918353; | |
} | |
h = h << 13 | h >>> 19; | |
return function() { | |
h = (h ^ h >>> 16) * 2246822507; | |
h = (h ^ h >>> 13) * 3266489909; | |
return (h ^= h >>> 16) >>> 0; | |
} | |
} | |
// pseudo-random number generator | |
function sfc32(seed, offset) { | |
var a = seed(); | |
var b = seed(); | |
var c = seed(); | |
var d = seed(); | |
return function () { | |
a >>>= 0; b >>>= 0; c >>>= 0; d >>>= 0; | |
var t = (a + b) | 0; | |
a = b ^ b >>> 9; | |
b = c + (c << 3) | 0; | |
c = (c << 21 | c >>> 11); | |
d = d + 1 | 0; | |
t = t + d | 0; | |
c = c + t | 0; | |
return (t >>> 0) / 4294967296 + offset; | |
} | |
} | |
// cosine interpolation | |
function interpolate(pa, pb, px) { | |
var ft = px * Math.PI, | |
f = (1 - Math.cos(ft)) * 0.5; | |
return pa * (1 - f) + pb * f; | |
} | |
// 1D perlin line generator | |
function perlin(prng, amp, wl, width) { | |
this.x = 0; | |
this.amp = amp; | |
this.wl = wl; | |
this.fq = 1 / wl; | |
this.prng = prng; | |
this.a = this.prng(); | |
this.b = this.prng(); | |
this.pos = []; | |
while (this.x < width) { | |
if (this.x % this.wl === 0) { | |
this.a = this.b; | |
this.b = this.prng(); | |
this.pos.push(this.a * this.amp); | |
} else { | |
this.pos.push(interpolate(this.a, this.b, (this.x % this.wl) / this.wl) * this.amp); | |
} | |
this.x++; | |
} | |
} | |
// octave generator | |
function generateNoise(prng, amp, wl, octaves, divisor, width) { | |
var result = []; | |
for (var i = 0; i < octaves; i++) { | |
result.push(new perlin(prng, amp, wl, width)); | |
amp /= divisor; | |
wl /= divisor; | |
} | |
return result; | |
} | |
// combines octaves together | |
function combineNoise(pl) { | |
var result = { | |
pos: [] | |
}; | |
for (var i = 0, total = 0, j = 0; i < pl[0].pos.length; i++) { | |
total = 0; | |
for (j = 0; j < pl.length; j++) { | |
total += pl[j].pos[i]; | |
} | |
result.pos.push(total); | |
} | |
return result.pos; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment