书名:代码本色:用编程模拟自然系统
作者:Daniel Shiffman
译者:周晗彬
ISBN:978-7-115-36947-5
0.6 Perlin噪声(一种更平滑的算法)
一个好的随机数生成器能产生互不关联且毫无规律的随机数。跟我们前面看到的一样,一定程度的随机性有利于有机体和生命活动的建模。然而,单独把随机性作为唯一指导原则是不够的,它并不完全符合自然界的特征。
1、Perlin噪声
Perlin噪声算法可用于生成各种自然特效,包括云层、地形和大理石的纹理。
Perlin噪声算法表现出了一定的自然性,因为它能生成符合自然排序(“平滑”)的伪随机数序列。
- 图0-5展示了Perlin噪声的效果,x轴代表时间;请注意曲线的平滑性。
- 图0-6展示了纯随机数的效果。
Processing内置了Perlin噪声算法的实现:noise()函数。noise()函数可以有1~3个参数,分别代表一维、二维和三维的随机数。
2、noise()函数
- Processing的noise()函数告诉我们噪声是通过几个“八度”计算出来的。
- 调用noiseDetail()函数会改变“八度”的数量以及各个八度的重要性,这反过来会影响noise()函数的行为。
- Ken Perlin有个在线讲座,能让你了解更多的噪声原理
(http://processing.org/reference/noise_.html)
(http://processing.org/reference/noiseDetail_.html)
(http://www.noisemachine.com/talk1/)
3、noise()函数的不同点
从概念上说,我们确实只需要用Perlin噪声算法得到0和窗口宽度之间的一个x坐标,但这并不是一个正确的实现。
random()函数的参数是目标随机数的最小值和最大值,但是noise()函数并非如此。
noise()函数的结果范围是固定的,它总是会返回一个介于0~1的结果。
后面我们会通过Processing的map()函数来改变结果的范围。
在此之前,先来了解noise()函数的参数。
我们可以把一维的Perlin噪声当作随着时间推移而发生变化的线性序列,比如:
时间 | 噪声值 |
---|---|
0 | 0.365 |
1 | 0.363 |
2 | 0.363 |
3 | 0.364 |
4 | 0.366 |
为了在Processing中得到某个时间点上的噪声值,我们必须传入noise()函数一个“指定的时间点”,比如:
float n = noise(3);
根据上面的表格,noise(3)会在时间点3返回0.364。为了能用draw()函数获取不同时刻的噪声值,我们可以传入一个时间变量作为参数。
float t = 3;
void draw(){
float n = noise(t); //返回指定时间点的噪声值
println(n);
}
上面的代码每次都会输出一样的结果。因为我们每次都在noise()函数中传入一个固定的时间点——3。递增时间变量t,我们就能得到不同的结果。
float t = 0; //一般从时间点0开始,但这个值可以是任意的
void draw(){
float n = noise(t);
println(n);
t+=0.01; //随时间向前移动
}
t增大的速度会影响噪声的平滑度。如果我们让t发生很大的跳跃,很多中间值将会被跳过,得到的值也更随机。
试着多次运行上面的代码,分别以0.01、0.02、0.05、0.1、0.0001的增量增大t,你会看到不同的结果。