2011-09-08 74 views
4

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

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

+1

这不是一个真正的问题:“不复制准确Perlin杂点”是非常开放-ended。你需要更具体地了解你要找的东西。 –

回答

1

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

但是,如果你绝对想用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 
1

我最近尝试翻译根·珀林的"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 
2

一个简单的方法来做到这一点,在MATLAB,由Nullprogramm blog显示在Octave是:

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 
+1

你好,我只想对这个简单的算法表示感谢,并补充说我通过改变一条简单的线改善了计算机的时间。 (m-1)/(2 ^(i-1)/(2^-1))+ 1)),i-1,'样条'); – Wli