window.addEventListener('load', function() { const canvas = this.document.getElementById('canvas1'); const ctx = canvas.getContext('2d'); canvas.width = 1500; canvas.height = 500; class Perlin { // number of points to generate #NUM_POINTS = 101; // number of prime numbers in each array #NUM_PRIMES = 5; #PRIME5 = [ 15731, 16069, 17579, 31963, 22453]; #PRIME6 = [ 789221, 790289, 811081, 211777, 566173]; #PRIME10 = [1376312589, 1480028201, 1500450271, 1000075057, 1023465798]; constructor(persist, octave) { this.persist = persist; this.octave = octave; this.#init(); console.log("points:"); console.log(this.points); } #init() { this.points = []; this.p5d = this.#PRIME5[Math.floor(Math.random() * 5)]; this.p6d = this.#PRIME6[Math.floor(Math.random() * 5)]; this.p10d = this.#PRIME10[Math.floor(Math.random() * 5)]; for(let i = 0; i < this.#NUM_POINTS; i++) { this.points[i] = this.#perlin1D(this.persist, this.octave, 0.1 * i); } } #perlin1D(persist, octave, x) { let total = 0.0; let freq = 0.0; let amp = 0.0; for(let i = 0; i < octave; i++) { freq = Math.pow(2,i); amp = Math.pow(persist, i); total += this.#interpolateNoise(x * freq) * amp; } return total; } /* * #interpolateNoise - performs a successive smoothing function on * the input value. * ARGUMENT: * x: float value to be smoothed. */ #interpolateNoise(x) { let intX = Math.floor(x); let fractionX = x - intX; let v1 = this.#smoothedNoise(intX); let v2 = this.#smoothedNoise(intX + 1); return this.#cosineInterpolation(v1, v2, fractionX); } /* * #smoothedNoise - smooths the output to make it look less random * * ARGUMENTS: * x: integer value to be smoothed. It is done by averaging between * the points before and after the given point. * * RETURNS: * a float value that has been "smoothed". */ #smoothedNoise(x) { return (this.#findNoise(x) /2) + (this.#findNoise(x - 1) / 4) + (this.#findNoise(x+1)/4); } #cosineInterpolation(a, b, x) { let ft = (x * Math.PI); let f = (1 - Math.cos(ft)) * 0.5; return a * (1 - f) + (b * f); } /* * findNoise - Random number generator. Unlike other RNG this method * will return the same number for the same input. * * ARGUMENTS: * x: an integer value * * RETURNS: * returns a floating point number between -1.0 and 1.0. * * NOTE: * original return value as published on * http://freespace.virgin.net/hugo.elias/models/m_perlin.htm */ #findNoise(x) { let z = (x << 13) ^ x; let y = (1.0 - (( z * (z * z * this.p5d + this.p6d) + this.p10d) & 0x7fffffff ) / 1073741824.0); return y; } } let perlin1 = new Perlin(0.3, 4); let perlin2 = new Perlin(0.3, 0.4); });