【问题标题】:Generate procedural\perlin noise in matlab在 matlab 中生成程序\柏林噪声
【发布时间】:2011-09-08 11:10:00
【问题描述】:

我正在寻找一种简单的方法来在 matlab 中生成类似于程序\柏林噪声的东西。

它只需要具有一般的 perlin 噪声特征,而不是完全复制 ken perlin 的方法。

【问题讨论】:

  • 这不是一个真正的问题:“不完全复制柏林噪声”是非常开放的。您需要更具体地了解您要查找的内容。

标签: matlab perlin-noise


【解决方案1】:

在 Matlab 中执行此操作的一种简单方法,如 Octave 中 Nullprogramm blog 所示:

n = 64;
m = 64;
im = zeros(n, m);
im = perlin_noise(im);

figure; imagesc(im); colormap gray;

function im = perlin_noise(im)

    [n, m] = size(im);
    i = 0;
    w = sqrt(n*m);

    while w > 3
        i = i + 1;
        d = interp2(randn(n, m), i-1, 'spline');
        im = im + i * d(1:n, 1:m);
        w = w - ceil(w/2 - 1);
    end

【讨论】:

  • 你好,我只是想感谢这个简单的小算法,并补充说我通过改变一个简单的行来改进它的计算机时间。当涉及到插值时,替换为 d = interp2(randn(ceil((n-1)/(2^(i-1))+1),ceil((m-1)/(2^(i-1) ))+1)), i-1, '样条');
【解决方案2】:

perlin 噪声实现已经存在于几种编程语言中,并且可以在 Internet 上免费获得。例如,Ken Perlin 的 homepage (3D version / 4D version) 上有一个可以与 Matlab 一起使用的 java 类。

但是,如果您绝对想使用 Matlab 语言,我想这只是“翻译”的问题,应该很简单。这是对尺寸 1 到 3 的尝试,应该可以。它没有优化也没有经过彻底测试(似乎有一些边界问题)。希望对你有帮助。

function noise=perlin(values,x,y,z)
if(numel(values)~=512)
    values=randperm(256)-1;
    values=[values values];
end
x=abs(x);
X=bitand(floor(x),255);
x=x-floor(x);
u=fade(x);
A=values(1+X);
noise=linterp(u,grad1d(values(1+X),x),grad1d(values(1+X+1),x-1));
if(nargin>2)
    y=abs(y);
    Y=bitand(floor(y),255);
    y=y-floor(y);
    v=fade(y);
    A=A+Y;
    B=values(1+X+1)+Y;
    noise=linterp(u,linterp(u,grad2d(values(1+A),x,y),grad2d(values(1+B),x-1,y)),linterp(u,grad2d(values(1+A+1),x,y-1),grad2d(values(1+B+1),x-1,y-1)));
end
if(nargin>3)
    z=abs(z);
    Z=bitand(floor(z),255);
    z=z-floor(z);
    w=fade(z);
    AA=values(1+A)+Z;
    AB=values(1+A+1)+Z;
    BA=values(1+B)+Z;
    BB=values(1+B+1)+Z;
    noise=linterp(  w, ... 
                    linterp(v, ... 
                            linterp(u, ... 
                                    grad3d(values(1+AA),x,y,z), ... 
                                    grad3d(values(1+BA),x-1,y,z)), ...
                            linterp(u, ...
                                    grad3d(values(1+AB),x,y-1,z), ...
                                    grad3d(values(1+BB),x-1,y-1,z))), ...
                    linterp(v, ...
                            linterp(u, ... 
                                    grad3d(values(1+AA+1),x,y,z-1), ... 
                                    grad3d(values(1+BA+1),x-1,y,z-1)), ...
                            linterp(u, ...
                                    grad3d(values(1+AB+1),x,y-1,z-1), ...
                                    grad3d(values(1+BB+1),x-1,y-1,z-1))));
end
end

function l=linterp(t,a,b)
l=a+t*(b-a);
end

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

function g=grad1d(hash,x)
if(bitand(hash,1))
    g=-x;
else
    g=x;
end
end

function g=grad2d(hash,x,y)
h=bitand(hash,3);
if(bitand(h,2))
    u=-x;
else
    u=x;
end
if(bitand(h,1))
    v=-y;
else
    v=y;
end
g=u+v;
end

function g=grad3d(hash,x,y,z)
h=bitand(hash,15);
if(h<8)
    u=x;
else
    u=y;
end
if(h<4)
    v=y;
elseif(h==12 || h==14)
    v=x;
else
    v=z;
end
if(bitand(h,1))
    if(bitand(h,2))
        g=-u-v;
    else
        g=-u+v;
    end
else
    if(bitand(h,2))
        g=u-v;
    else
        g=u+v;
    end
end
end

【讨论】:

    【解决方案3】:

    我最近尝试翻译 Ken Perlin 的"Improved Noise"。结果在这篇文章的最后。请注意,制作 256 x 256 矩阵需要 10 秒。使用imagesc 进行可视化。

    并不是我发现gradient(rand(w, h)) 似乎给出了不错的结果。我对噪音了解不多,所以我不知道这是否是“同一件事”,但它似乎确实有效。对于较大的网格,您只需在较小的rand 中插入点。

    function n = noise(x, y, z)
    % noise(x, y, z) generates (I believe) 3 dimensional noise. To use, iterate
    % through your array and generate each value with a call this function.
    % Note that it is very slow.
    % 
    % Based Ken Perlin's "Improved Noise" in 2001, or 2002, or something.
    
    % The unit cube which contains this point
    uX = mod(floor(x), 256);
    uY = mod(floor(y), 256);
    uZ = mod(floor(z), 256);
    
    % Find relative x, y, z of point in cube
    x =x- floor(x);
    y =y- floor(y);
    z =z- floor(z);
    
    % The mysterious "fade" function
    fade = @(t) t * t * t * (t * (t * 6 - 15) + 10);
    
    % Compute fade curved for each of x, y, z
    u = fade(x);
    v = fade(y);
    w = fade(z);
    
    % Hash coordinates of the 8 cube corners
    p_half = randi(256, 256, 1) - 1;
    p = [p_half, p_half];
    
    a = p(1+uX) + uY;
    aa = p(1+a) + uZ;
    ab = p(1+a + 1) + uZ;
    
    b = p(1+uX + 1) + uY;
    ba = p(1+b) + uZ;
    bb = p(1+b + 1) + uZ;
    
    % "Lerp" is a shorter, more confusing name for "linear interpolation"
    lerp = @(t, a, b) a + t * (b - a);
    
    % This is how he gets the gradient
        function g = grad(hash, x, y, z)
            %Convert the low 4 bits of hash code into 12 gradient directions
            h = mod(hash, 16);
    
            % 50% chance for u to be on x or y
            if h < 8
                u_comp = x;
            else
                u_comp = y;
            end
    
            % 50% chance to reverse either component
            if mod(h, 2) == 0
                u_comp = -u_comp;
            end
    
            % 12.5% chance for v to be on x, 25% chance to be on y, 62.5% chance for z
            if (h == 12 || h == 14)
                v_comp = x;
            elseif (h < 4)
                v_comp = y;
            else
                v_comp = z;
            end
    
            % 50% chance to reverse either component
            if mod(h/2, 2) == 0
                v_comp = -v_comp;
            end
    
            g = u_comp + v_comp;
        end
    
    % And add blended results from 8 corners of cube
    n = lerp(w, lerp(v, lerp(u, grad(p(1+aa), x, y, z), ...
        grad(p(1+ba), x - 1, y, z)), ...
        lerp(u, grad(p(1+ab), x, y - 1, z), ...
        grad(p(1+bb), x - 1, y - 1, z))), ...
        lerp(v, lerp(u, grad(p(1+aa + 1), x, y, z - 1), ...
        grad(p(1+ba + 1), x - 1, y, z - 1)), ...
        lerp(u, grad(p(1+ab + 1), x, y - 1, z - 1), ...
        grad(p(1+bb + 1), x - 1, y - 1, z - 1))));
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-29
      • 2012-01-29
      • 2017-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多