JavaScript 单工/柏林噪声
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8405526/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JavaScript simplex / perlin noise
提问by Alex Turpin
I'm trying to create a perlin / simplex / value noise function in JavaScript that will give results similar to the following:
我正在尝试在 JavaScript 中创建一个 perlin/simplex/value 噪声函数,它将给出类似于以下的结果:
(Note: this image has already had a treshold applied. I want it without the treshold.)
(注意:此图像已经应用了阈值。我希望它没有阈值。)
I've been looking all over the internet for 2 days now. There are plenty of links explaining noise and a lot of code, but none in JavaScript, and whenever I try to convert it, I get weird results. Here are some of my attemps:
我已经在互联网上寻找了 2 天了。有很多链接解释了噪音和大量代码,但在 JavaScript 中没有,每当我尝试转换它时,我都会得到奇怪的结果。以下是我的一些尝试:
- http://jsfiddle.net/GZCye/
- http://jsfiddle.net/Lk56f/(based on this)
- http://pastebin.com/nMA40SrL(doesn't run in Fiddle for some reason, based on this
- http://jsfiddle.net/GZCye/
- http://jsfiddle.net/Lk56f/(基于此)
- http://pastebin.com/nMA40SrL(基于此,出于某种原因不在 Fiddle 中运行
I think part of the problem might stem from the use of the bitwise operators in JavaScript, where it is difficult to enforce the type of a number.
我认为部分问题可能源于 JavaScript 中按位运算符的使用,其中很难强制执行数字的类型。
What I'm looking for is an example of working, JavaScript noise (whatever type).
我正在寻找的是一个工作的例子,JavaScript 噪音(无论是什么类型)。
I'd also be willing to grant a bounty for any information pertaining to the parameters that could lead to a pattern similar to the image I posted (before threshold) or any optimization tips since I'll need this to run as fast as possible (in JavaScript nonetheless).
我也愿意为与参数相关的任何信息提供赏金,这些信息可能导致类似于我发布的图像(阈值之前)或任何优化提示的模式,因为我需要它尽可能快地运行(在 JavaScript 中)。
采纳答案by Alex Turpin
I will be using the code found on this Gist.
回答by Loktar
I did something like this a while back, however I used midpoint displacement. If you can figure out whats going on it could be helpful,
不久前我做了类似的事情,但是我使用了中点置换。如果你能弄清楚发生了什么,它可能会有所帮助,
http://www.somethinghitme.com/projects/canvasterrain/
http://www.somethinghitme.com/projects/canvasterrain/
Its also here
它也在这里
https://github.com/loktar00/Javascript-Canvas-Terrain-Generator
https://github.com/loktar00/Javascript-Canvas-Terrain-Generator
And here is a fiddle with just the noise part implemented with some cool lighting,
这是一个用一些很酷的灯光实现的噪音部分的小提琴,
http://jsfiddle.net/loktar/4qAxZ/
http://jsfiddle.net/loktar/4qAxZ/
Good luck :).
祝你好运 :)。
回答by lencinhaus
I know this is pretty old, but maybe it can still be useful for someone else. I've built a javascript app that renders Perlin and Simplex noise to an HTML5 canvas, check it out here: http://lencinhaus.github.com/canvas-noise
我知道这已经很老了,但也许它对其他人仍然有用。我已经构建了一个将 Perlin 和 Simplex 噪声渲染到 HTML5 画布的 javascript 应用程序,请在此处查看:http: //lencinhaus.github.com/canvas-noise
The app allows to tweak every parameter involved in noise calculation and rendering and to save the resulting texture. It also adds the parameters to the URL, so that it can be shared. For example, this configurationproduces a texture very similar to the one you showed.
该应用程序允许调整噪声计算和渲染中涉及的每个参数并保存生成的纹理。它还将参数添加到 URL,以便它可以共享。例如,此配置产生的纹理与您展示的纹理非常相似。
Hope that helps!
希望有帮助!
回答by Drew Noakes
Here's what the code I ended up with for 2D / 3D Perlin noise. Note that it uses RequireJS's AMD module syntax, but you can strip that away if you're not using an AMD loader.
这是我最终得到的 2D/3D Perlin 噪声代码。请注意,它使用 RequireJS 的 AMD 模块语法,但如果您不使用 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)
)
)
);
}
};
}
);
回答by Evhz
I came up with this solution which gave better results for my use case:
我想出了这个解决方案,它为我的用例提供了更好的结果:
http://asserttrue.blogspot.com/2011/12/perlin-noise-in-javascript_31.html
http://asserttrue.blogspot.com/2011/12/perlin-noise-in-javascript_31.html
It's using a big permutation matrix:
它使用了一个大的置换矩阵:
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
];
Use it as:
将其用作:
pn = PerlinNoise()
n = pn.noise( random_x, random_y, .8 )