javascript algorithm perlin-noise procedural-generation simplex-noise

JavaScript simplex/perlin noise



algorithm perlin-noise (5)

Estoy intentando crear una función de ruido perlin / simplex / value en JavaScript que dará resultados similares a los siguientes:

(Nota: a esta imagen ya se le ha aplicado un dominio. Lo quiero sin el compromiso.)

He estado buscando por todo el internet por 2 días ahora. Hay muchos enlaces que explican ruido y mucho código, pero ninguno en JavaScript, y cada vez que intento convertirlo obtengo resultados extraños. Aquí están algunos de mis intentos:

Creo que parte del problema podría deberse al uso de operadores bitwise en JavaScript, donde es difícil imponer el tipo de un número.

Lo que estoy buscando es un ejemplo de trabajo, ruido de JavaScript (cualquier tipo).

También estaría dispuesto a otorgar una recompensa por cualquier información relacionada con los parámetros que podría conducir a un patrón similar al de la imagen que publiqué (antes del umbral) o cualquier sugerencia de optimización, ya que la necesitaré para ejecutarme lo más rápido posible ( en JavaScript no obstante).


Aquí está el código con el que terminé para el ruido Perlin 2D / 3D. Tenga en cuenta que utiliza la sintaxis del módulo AMD de RequireJS, pero puede eliminarla si no está utilizando un cargador AMD.

define( [], function() { function fade(t) { return t * t * t * (t * (t * 6 - 15) + 10); } function lerp(t, a, b) { return a + t * (b - a); } function grad(hash, x, y, z) { // Convert lo 4 bits of hash code into 12 gradient directions. var h = hash & 15, u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z; return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); } function scale(n) { return (1 + n) / 2; } var p = new Array(512); var permutation = [ 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180 ]; for (var i = 0; i < 256; i++) { p[256 + i] = p[i] = permutation[i]; } return { /** Returns a number between 0 and 1. */ noise3d: function(x, y, z) { // Find unit cube that contains point. var X = Math.floor(x) & 255, Y = Math.floor(y) & 255, Z = Math.floor(z) & 255; // Find relative x,y,z of point in cube. x -= Math.floor(x); y -= Math.floor(y); z -= Math.floor(z); // Compute fade curves for each of x,y,z. var u = fade(x), v = fade(y), w = fade(z); // Hash coordinates of the corners. var A = p[X ] + Y, AA = p[A] + Z, AB = p[A + 1] + Z, B = p[X + 1] + Y, BA = p[B] + Z, BB = p[B + 1] + Z; // Add blended results from 8 corners of cube. return scale( lerp( w, lerp( v, lerp( u, grad(p[AA], x, y, z), grad(p[BA], x - 1, y, z) ), lerp( u, grad(p[AB], x, y - 1, z), grad(p[BB], x - 1, y - 1, z) ) ), lerp( v, lerp( u, grad(p[AA + 1], x, y, z - 1), grad(p[BA + 1], x - 1, y, z - 1) ), lerp( u, grad(p[AB + 1], x, y - 1, z - 1), grad(p[BB + 1], x - 1, y - 1, z - 1) ) ) ) ); }, /** Returns a number between 0 and 1. */ noise2d: function(x, y) { // Find unit square that contains point. var X = Math.floor(x) & 255, Y = Math.floor(y) & 255; // Find relative x,y of point in square. x -= Math.floor(x); y -= Math.floor(y); // Compute fade curves for each of x,y. var u = fade(x), v = fade(y); // Hash coordinates of the corners. var A = p[X ] + Y, AA = p[A], AB = p[A + 1], B = p[X + 1] + Y, BA = p[B], BB = p[B + 1]; // Add blended results from the corners. return scale( lerp( v, lerp( u, grad(p[AA], x, y, 0), grad(p[BA], x - 1, y, 0) ), lerp( u, grad(p[AB], x, y - 1, 0), grad(p[BB], x - 1, y - 1, 0) ) ) ); } }; } );



Sé que esto es bastante antiguo, pero tal vez aún pueda ser útil para otra persona. Construí una aplicación javascript que hace que el ruido Perlin y Simplex se convierta en un lienzo HTML5, échale un vistazo aquí: http://lencinhaus.github.com/canvas-noise

La aplicación permite ajustar todos los parámetros involucrados en el cálculo y la representación del ruido y guardar la textura resultante. También agrega los parámetros a la URL, para que pueda compartirse. Por ejemplo, esta configuración produce una textura muy similar a la que mostró.

¡Espero que ayude!


Se me ocurrió esta solución que dio mejores resultados para mi caso de uso:

http://asserttrue.blogspot.com/2011/12/perlin-noise-in-javascript_31.html

Está utilizando una gran matriz de permutación:

var permutation = [ 151,160,137,91,90,15, 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 ];

Úsalo como:

pn = PerlinNoise() n = pn.noise( random_x, random_y, .8 )


Usaré el código que se encuentra en este Gist.