为什么我的Perlin噪声发生器会产生这种波浪形图案?

时间:2017-04-28 17:44:54

标签: javascript perlin-noise noise-generator

我开始学习有关perlin噪音的生成,我想尝试用JavaScript创建自己的生成器。为了让我开始,我一直在跟随this youtube tutorial.一起尝试复制他们的基本实现。我也在阅读this article.

我提供了jsFiddle我的实施,其中显示了我正在做什么以及输出是什么。我在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值。 (最不可能)

我真的想深究这一点。在此先感谢您的帮助! :)

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

0 个答案:

没有答案