加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

perlin噪声函数

发布时间:2020-12-15 23:47:39 所属栏目:大数据 来源:网络整理
导读:原文链接:http://www.cnblogs.com/mikewolf2009/articles/1608087.html 许多人在他们的程序中使用“随机数产生器”,以使得物体的运动行为更加自然,或者用来生成纹理。随机数产生器在一些情况下很有用,但是它们生成的结果和自然结果相比,往往显得比较粗

原文链接:http://www.cnblogs.com/mikewolf2009/articles/1608087.html

许多人在他们的程序中使用“随机数产生器”,以使得物体的运动行为更加自然,或者用来生成纹理。随机数产生器在一些情况下很有用,但是它们生成的结果和自然结果相比,往往显得比较粗糙和生硬。这篇文章介绍使用广泛的Perlin函数,它常用在模拟自然物体的地方,比如地形,海水等。

自然物体通常是分形的,有各种各样的层次细节,比如山的轮廓,通过高度区分就有高山(mountain,高度变化大)、山丘(hill,高度变化适中)、巨石(高度变化小)?、石头(高度变化很小)等。另外,比如草地、海浪、跑动的蚂蚁、摇晃的树枝、风、大理石的花纹等等,这些都呈现出了或大或小的细节变化。Perlin噪声函数通过噪声函数来模拟这些自然景观。

要构造一个Perlin函数,你首先需要一个噪声函数和一个插值函数

?

1、?噪声函数

噪声函数本质上就是一个基于种子的随机数产生器。输入参数为一个整数,输出结果为基于输入参数的随机数。如果你两次输入同样的参数,则结果都是一样的。

左上图是一个噪声函数例子,它的输出值范围是[0,1],分布范围在x轴上。右上图是通过光滑插值函数处理后的结果。

在进一步学习Perlin函数之前,我们先看一些定义,其实这些都是高中物理的概念,很简单。比如上图的正弦波,波长(Wavelength)就是两个波谷指尖的距离,频率就是1/Wavelength,波幅(Amplitude)就是波的高度。

?

2、?创建Perlin噪音函数

假如现在你有各种各样不同频率和幅度的光滑函数(smooth function),把他们组合在一起,就能产生一个比较好的Perlin噪声函数。

??????????

?

?

组合在一起后的效果如下图,是不是很类似山的形状,确实很多3d程序中的地形就是利用2维的噪声函数。

?

下面我们看看单个2维光滑函数,组合在一起形成的2维噪声函数:

?

?

?

?

?

?

下面是各个函数组合在一起的效果:

我们现在比较关注,把这些噪声函数叠加在一起时候,如何选择他们的频率和幅度?在上面一维的例子中,后面的每个函数的频率是前面的2倍,幅度是前面1/2,通常是这样来做,你也可以自己尝试其它的频率和幅度的组合,看看效果如何,比如对于小山丘,你可以使用大幅度低频率以及小幅度高频率,看看生成的山丘又何不同,甚至你可以用地频率低幅度生成岩石表面。

通常定义Persistence为幅度/频率,这是分形几何的发明人Mandelbrot创造的。Matt也定义Persistence的概念,而且更加直观,它的定义如下:

frequency = 2i
amplitude = persistencei

?

i表示增加的第i个噪声函数,下面的图很好的解释了这个概念:

?

Frequency

1

?

2

?

4

?

8

?

16

?

32

?

?

?

Persistence = 1/4

?

+

?

+

?

+

?

+

?

+

?

=

?

?

Amplitude:

1

?

1/4

?

1/16

?

1/64

?

1/256

?

1/1024

?

result

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

Persistence = 1/2

?

+

?

+

?

+

?

+

?

+

?

=

?

?

Amplitude:

1

?

1/2

?

1/4

?

1/8

?

1/16

?

1/32

?

result

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

Persistence = 1 / root2

?

+

?

+

?

+

?

+

?

+

?

=

?

?

Amplitude:

1

?

1/1.414

?

1/2

?

1/2.828

?

1/4

?

1/5.656

?

result

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

Persistence = 1

?

+

?

+

?

+

?

+

?

+

?

=

?

?

Amplitude:

1

?

1

?

1

?

1

?

1

?

1

?

result

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

Octaves(倍频函数):

我们增加的函数称作octave函数.,主要是因为后面的每个函数都是前面函数频率的2倍。增加octave函数的数量取决于你。这儿我给的建议是:如果你用Perlin函数渲染图形图像,记住太高的频率可能不能显示,因为屏幕像素已经不能表示这些细节。一些Perlin噪音函数的实现可以根据屏幕限制,自动调节octave函数的数量。另外,当幅度太小时,也要停止增加octave函数。

?

下面我们看一个简单的噪音函数(一个随机数产生器)的代码,它返回浮点数[-1,1]


function?IntNoise(32-bit?integer:?x)??????????????????
?
????x?
=?(x<<13)?^?x;
????
return?(?1.0?-?(?(x?*?(x?*?x?*?15731?+?789221)?+?1376312589)?&?7fffffff)?/?1073741824.0);????
?
?end?IntNoise?function
如果我们需要几个不同的随机数产生器的时候,可以选用稍微有点差别的种子(一般为素数)。

下面看看插值函数,最简单的插值函数是线性插值函数:其中x[0,1],可以看到,线性插值生成的曲线都是分段的直线。

function?Linear_Interpolate(a,?b,?x)
????????
return ?a * ( 1 - x)? + ?b * x
?end?of?function
?

?

Cosine插值函数:

相对来讲,它插值的结果比较光滑。

?

function?Cosine_Interpolate(a,?x)
????????ft?
= ?x? * ? 3.1415927
????????f?
= ?( 1 ? - ?cos(ft))? * ?. 5
?
????????
return ?a * ( 1 - f)? + ?b * f
?end?of?function
Cubic插值:

三次插值产生的曲线很光滑,但是要以牺牲速度为代价。该函数接收5个参数,四个顶点数据,一个x值,

v0 = the point before a

v1 = the point a

v2 = the point b

v3 = the point after b

?

?

?


function?Cubic_Interpolate(v0,?v1,?v2,?v3,x)
????????P?
=?(v3?-?v2)?-?(v0?-?v1)
????????Q?
=?(v0?-?v1)?-?P
????????R?
=?v2?-?v0
????????S?
=?v1
?
????????
return?Px3?+?Qx2?+?Rx?+?S
?end?of?function
对噪音结果可以通过mean值滤波的方式来处理,处理后的结果会更光滑:

?

?

1维的光滑函数:

复制代码

function?Noise(x)
????.
????.
?end?function
?
?function?SmoothNoise_1D(x)
?
????
return ?Noise(x) / 2 ? + ?Noise(x - 1 ) / 4 ? + ?Noise(x + 1 ) / 4
?
?end?function

复制代码

2维的光滑函数:
?


?function?Noise(x,?y)
????.
????.
?end?function
?
?function?SmoothNoise_2D(x
>,?y)
????
????corners?
=?(?Noise(x-1,?y-1)+Noise(x+1,?y-1)+Noise(x-1,?y+1)+Noise(x+1,?y+1)?)?/?16
????sides???
=?(?Noise(x-1,?y)?+Noise(x+1,?y)?+Noise(x,?y-1)?+Noise(x,?y+1)?)?/?8
????center?
=?Noise(x,?y)?/?4
?
????
return?corners?+?sides?+?center
?
?
?end?function

3、?最终的Perlin噪声函数

Perlin噪声函数主要是通过一个循环,每个循环迭代增加一个2倍频率的octave函数,每次迭代调用不同的噪声函数Noise.

?1维Perlin函数的伪代码:

?


function?Noise1(integer?x)
????x?
=?(x<<13)?^?x;
????
return?(?1.0?-?(?(x?*?(x?*?x?*?15731?+?789221)?+?1376312589)?&?7fffffff)?/?1073741824.0);????
??end?function


??function?SmoothedNoise_1(
float?x)
????
return?Noise(x)/2??+??Noise(x-1)/4??+??Noise(x+1)/4
??end?function


??function?InterpolatedNoise_1(
float?x)

??????integer_X????
=?int(x)
??????fractional_X?
=?x?-?integer_X

??????v1?
=?SmoothedNoise1(integer_X)
??????v2?
=?SmoothedNoise1(integer_X?+?1)

??????
return?Interpolate(v1?,?v2?,?fractional_X)

??end?function


??function?PerlinNoise_1D(
float?x)

??????total?
=?0
??????p?
=?persistence
??????n?
=?Number_Of_Octaves?-?1

??????loop?i?from?
0?to?n

??????????frequency?
=?2i
??????????amplitude?
=?pi

??????????total?
=?total?+?InterpolatedNoisei(x?*?frequency)?*?amplitude

??????end?of?i?loop

??????
return?total

??end?function

?

?2维的Perlin函数代码:
?
 
 

function?Noise1(integer?x,?integer?y) ????n?=?x?+?y?*?57 ????n?=?(n<<13)?^?n; ????return?(?1.0?-?(?(n?*?(n?*?n?*?15731?+?789221)?+?1376312589)?&?7fffffff)?/?1073741824.0);???? ??end?function ??function?SmoothNoise_1(float?x,?float?y) ????corners?=?(?Noise(x-1,?y+1)?)?/?16 ????sides???=?(?Noise(x-1,?y)??+Noise(x+1,?y)??+Noise(x,?y-1)??+Noise(x,?y+1)?)?/??8 ????center??=??Noise(x,?y)?/?4 ????return?corners?+?sides?+?center ??end?function ??function?InterpolatedNoise_1(float?x,?float?y) ??????integer_X????=?int(x) ??????fractional_X?=?x?-?integer_X ??????integer_Y????=?int(y) ??????fractional_Y?=?y?-?integer_Y ??????v1?=?SmoothedNoise1(integer_X,?????integer_Y) ??????v2?=?SmoothedNoise1(integer_X?+?1,?integer_Y) ??????v3?=?SmoothedNoise1(integer_X,?????integer_Y?+?1) ??????v4?=?SmoothedNoise1(integer_X?+?1,?integer_Y?+?1) ??????i1?=?Interpolate(v1?,?fractional_X) ??????i2?=?Interpolate(v3?,?v4?,?fractional_X) ??????return?Interpolate(i1?,?i2?,?fractional_Y) ??end?function ??function?PerlinNoise_2D(float?x,?float?y) ??????total?=?0 ??????p?=?persistence ??????n?=?Number_Of_Octaves?-?1 ??????loop?i?from?0?to?n ??????????frequency?=?2i ??????????amplitude?=?pi ??????????total?=?total?+?InterpolatedNoisei(x?*?frequency,?y?*?frequency)?*?amplitude ??????end?of?i?loop ??????return?total ??end?function

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读