Perlin Noise:网格单元之间的清晰轮廓(Matlab)

时间:2014-11-15 15:08:15

标签: matlab noise perlin-noise

我认为这个问题与this post无关。

我正在尝试在Matlab中实现2D经典Perlin噪声。我一直在建造this site作为参考。但是,我的程序给了我“非平滑”的噪音,如下所示。看起来局部插值(在每个网格单元内)工作正常,但网格单元之间存在连续性问题。在我看来,噪音几乎那里,除了锐度,我无法确定原因。如果你看一下等高线图,网格单元之间会有一些匹配,所以我不是(或者我不相信我)为噪声计算选择错误的网格点。

blocky perlin noise

enter image description here

这是我的代码。我此刻并不是为了提高速度或效率(它非常慢)。

导致电网不连续的原因是什么?

function noise = getPerlinNoise(xPix, yPix, resolution, seed)

% allocate 2D noise map
noise = zeros(xPix, yPix);

% calculate grid spacing
gridSpacing = 1 / resolution;

% allocate gradient matrix
xGridSize = ceil(xPix/gridSpacing) + 1;
yGridSize = ceil(yPix/gridSpacing) + 1;
gradients = zeros(xGridSize, yGridSize, 2);

% seed PRNG for repeatable results
rng(seed);

% compute random gradient vectors (populate 'gradients' matrix)
for i = 1:xGridSize
    for j = 1:yGridSize

        % randomize gradients by choosing angle between 0 and 2*pi
        angle = rand * 2 * pi;

        % insert components into gradients matrix
        % Because point is on unit circle, no vector normalization is needed
        gradients(i, j, 1) = cos(angle);
        gradients(i, j, 2) = sin(angle);

    end
end

% actually calculate the noise
for i = 0:xPix - 1
    for j = 0:yPix - 1
        noise(i + 1, j + 1) = perlin(i, j);
    end
end

% ------
% END
% ------

%=====================================

    function val = lerp(a, b, w)
        % linearly interpolates between a and b with weight w
        val = a + w * (b - a);
    end

%=====================================

    function val = fade(t)
        % improved perlin fade function
        val = 6 * t^5 - 15 * t^4 + 10 * t^3;
    end

%=====================================


    function val = perlin(x, y)
        % computes perlin noise at pixel coordinates (x, y)

        % find grid points that a specific point will be located inside
        xi = floor(x / gridSpacing) + 1;     % +1 because Matlab arrays are 1-based 
        xf = xi + 1;
        yi = floor(y / gridSpacing) + 1;
        yf = yi + 1;

        % get coords of cell corners in pixel coordinates
        xCellMin = (xi - 1) * gridSpacing;
        xCellMax = xCellMin + gridSpacing;
        yCellMin = (yi - 1) * gridSpacing;
        yCellMax = yCellMin + gridSpacing;        

        % calculate distance vectors from grid points to current point
        A = [x - xCellMin, y - yCellMin];
        B = [x - xCellMax, y - yCellMin];
        C = [x - xCellMin, y - yCellMax];
        D = [x - xCellMax, y - yCellMax];        

        % calculate influence of gradient vectors by using dot product
        s = dot(A, [gradients(xi, yi, 1), gradients(xi, yi, 2)] );
        t = dot(B, [gradients(xi, yf, 1), gradients(xi, yf, 2)] );
        u = dot(C, [gradients(xf, yi, 1), gradients(xf, yi, 2)] );
        v = dot(D, [gradients(xf, yf, 1), gradients(xf, yf, 2)] );

        % interpolate to get final noise value at (x, y)
        sx = fade((x - xCellMin) / gridSpacing);
        sy = fade((y - yCellMin) / gridSpacing);

        a = lerp(s, t, sx);
        b = lerp(u, v, sx);
        val = lerp(a, b, sy);      

    end
end

============================================== < / p>

更正代码

(感谢MarkV)

    % calculate influence of gradient vectors by using dot product
    s = dot(A, [gradients(xi, yi, 1), gradients(xi, yi, 2)] );
    t = dot(B, [gradients(xi, yf, 1), gradients(xi, yf, 2)] );
    u = dot(C, [gradients(xf, yi, 1), gradients(xf, yi, 2)] );
    v = dot(D, [gradients(xf, yf, 1), gradients(xf, yf, 2)] );

应更改为

    % calculate influence of gradient vectors by using dot product
    s = dot(A, [gradients(xi, yi, 1), gradients(xi, yi, 2)] );
    t = dot(B, [gradients(xf, yi, 1), gradients(xf, yi, 2)] );
    u = dot(C, [gradients(xi, yf, 1), gradients(xi, yf, 2)] );
    v = dot(D, [gradients(xf, yf, 1), gradients(xf, yf, 2)] );

1 个答案:

答案 0 :(得分:0)

在我看来,就像你改变B&amp; C在这里。

% calculate influence of gradient vectors by using dot product
s = dot(A, [gradients(xi, yi, 1), gradients(xi, yi, 2)] );
t = dot(C, [gradients(xi, yf, 1), gradients(xi, yf, 2)] ); % use C
u = dot(B, [gradients(xf, yi, 1), gradients(xf, yi, 2)] ); % use B
v = dot(D, [gradients(xf, yf, 1), gradients(xf, yf, 2)] );