Javascript 为什么我的柏林噪声发生器会产生这种扭曲的图案?

Javascript 为什么我的柏林噪声发生器会产生这种扭曲的图案?,javascript,perlin-noise,noise-generator,Javascript,Perlin Noise,Noise Generator,我已经开始学习柏林噪声生成,我想尝试用JavaScript制作自己的生成器。为了让我开始,我一直在跟随,试图复制它们的基本实现。我也一直在读书 我已经提供了我的实现的一个示例,它显示了我正在做什么以及输出是什么。我在youtube教程中看到的不是平滑流动、冒泡的噪音,而是紧密收缩的黑色曲线。这是一张照片: 这是我的生成器代码: var p = [151,160,137,91,90,15, 131,13,201,95,96,53,194,233

我已经开始学习柏林噪声生成,我想尝试用JavaScript制作自己的生成器。为了让我开始,我一直在跟随,试图复制它们的基本实现。我也一直在读书

我已经提供了我的实现的一个示例,它显示了我正在做什么以及输出是什么。我在youtube教程中看到的不是平滑流动、冒泡的噪音,而是紧密收缩的黑色曲线。这是一张照片:

这是我的生成器代码:

var p = [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,
         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]



function generatePerlinNoise(x, y){
  // Determine gradient cell corners
  var xi = Math.floor(x) & 255;
  var yi = Math.floor(y) & 255;

  var g1 = p[p[xi] + yi];
  var g2 = p[p[xi + 1] + yi];
  var g3 = p[p[xi] + yi + 1];
  var g4 = p[p[xi + 1] + yi + 1];

  // Get point within gradient cell
  var xf = x - Math.floor(x);
  var yf = y - Math.floor(y);

  // Get dot products at each corner of the gradient cell
  var d1 = generateGradient(g1, xf, yf);
  var d2 = generateGradient(g2, xf - 1, yf);
  var d3 = generateGradient(g3, xf, yf - 1);
  var d4 = generateGradient(g4, xf - 1, yf - 1);

  var xFade = fade(xf);
  var yFade = fade(yf);

  var x1Interpolated = linearInterpolate(xFade, d1, d2);
  var x2Interpolated = linearInterpolate(xFade, d3, d4);
  var noiseValue = linearInterpolate(yFade, x1Interpolated, x2Interpolated);

  return noiseValue;
}

function generateGradient(hash, x, y){
  switch(hash & 3){
    case 0: return x + y;
    case 1: return -x + y;
    case 2: return x - y;
    case 3: return -x - y;
    default: return 0;
                 }
}

// This is the fade function described by Ken Perlin
function fade(t){
  return t * t * t * (t * (t * 6 - 15) + 10); 
}

function linearInterpolate(amount, left, right){
  return ((1-amount) * left + (amount * right))
}
我利用生成器函数,将像素x和y值除以画布高度,然后按频率变量进行缩放:

        var freq = 12;

        var noise = generatePerlinNoise((x/canvas.offsetHeight)*freq, (y/canvas.offsetHeight)*freq);
        noise = Math.abs(noise);
我目前正在使用“噪波”值生成灰度颜色值:

        var blue = Math.floor(noise * 0xFF); // Scale 255 by our noise value,
                                             // and take it's integer portion
        var green =  Math.floor(noise * 0xFF);
        var red =  Math.floor(noise * 0xFF);

        data[i++] = red;
        data[i++] = green;
        data[i++] = blue;
        data[i++] = 255;
对我来说,这一点是为了学习更多关于噪声生成和javascript的知识。我试着思考这个问题,并做了一些观察:

  • 没有可见的瑕疵,所以我的淡入淡出功能似乎工作正常
  • 似乎没有任何重复的模式,所以这是一个好迹象
  • 我去生成一个完整的灰度值范围——不仅仅是黑白
  • 一般的问题似乎是每个像素的梯度如何影响其相邻像素:我的像素似乎以固定宽度的蛇形绳索聚集在一起。似乎提供的梯度向量选项和用于随机选择它们的排列表将控制这一点,但我的是教程中的一个精确副本:相同的4个向量,每个向量指向45度的象限,以及标准排列表
这让我很难弄清楚原因是什么。我的普遍怀疑归结为:

  • 我把算法弄得一团糟,这是我一直忽略的一种微妙的方式。(最有可能)
  • JavaScript做一些我忽略的事情的方式有一个微妙的区别。(也许)
  • 我正确地生成了噪波,但错误地将结果应用于画布图像数据中使用的RGB值。(可能性最小)
我真的很想弄清这件事的真相。提前感谢您的帮助!:)

另外:我确实认为这个模式很酷,这是一个学习练习,所以如果有人能分享我为什么会得到这个模式的见解,那就太好了