• (转)perlin噪声函数


      http://freespace.virgin.net/hugo.elias/models/m_perlin.htm

    许多人在他们的程序中使用“随机数产生器”,以使得物体的运动行为更加自然,或者用来生成纹理。随机数产生器在一些情况下很有用,但是它们生成的结果和自然结果相比,往往显得比较粗糙和生硬。这篇文章介绍使用广泛的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, b, 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)+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

      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 , v2 , 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
  • 相关阅读:
    CF-478C
    HDU-2074-叠筐
    HDU-2037-今年暑假不AC
    POJ-2785-4 Values whose Sum is 0
    HDU-1160-FatMouse's Speed
    HDU-1297-Children’s Queue
    Redis客户端管理工具的安装及使用
    Redis客户端管理工具,状态监控工具
    memcached可视化客户端工具
    javascript回调函数
  • 原文地址:https://www.cnblogs.com/lancidie/p/1855653.html
Copyright © 2020-2023  润新知