我正在寻找一种在matlab中生成类似于程序\ perlin噪声的简单方法。
它只需要具有一般的perlin噪声特性,而不是完全复制ken perlin的方法。
答案 0 :(得分: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 :(得分:1)
perlin噪声实现已经存在于几种编程语言中,并且可以在互联网上免费获得。例如,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
答案 2 :(得分:1)
我最近试图翻译Ken Perlin的"Improved Noise"。结果发表在这篇文章的最后。请注意,制作256乘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