Perlin Noise(柏林噪声)

Perlin Noise(柏林噪声),第1张

概述很多人都在其方案中使用随机数生成器去创造不可预测,使物体的运动和行为显得更加自然,或者生成纹理。 随机数发生器,肯定有其用途,但其输出可以是过于苛刻,显得自然。 本文将介绍一个函数,它具有非常广泛的用途,更比我能想到的,但基本上任何地方你需要的东西,看看起源于自然。 更重要的是它的输出可以很容易地定制,以满足您的需求。 如果您在大自然中的许多事情,你会发现它们是分形。 他们有不同层次的细节。 一个 @H_502_0@ @H_502_0@

很多人都在其方案中使用随机数生成器去创造不可预测,使物体的运动和行为显得更加自然,或者生成纹理。 随机数发生器,肯定有其用途,但其输出可以是过于苛刻,显得自然。 本文将介绍一个函数,它具有非常广泛的用途,更比我能想到的,但基本上任何地方你需要的东西,看看起源于自然。 更重要的是它的输出可以很容易地定制,以满足您的需求。


如果您在大自然中的许多事情,你会发现它们是分形。 他们有不同层次的细节。 一个常见的​​例子是一个山脉的轮廓。 它包含了大的变化的高度(山),中等变化(丘陵),小的变化(砾石),微小的变化(石头)。 。 。 你可以去上。 几乎所有的东西看的草片状分布于田间,海中的波浪,蚂蚁,树枝,大理石花纹,风的运动动作。 所有这些现象表现出了相同的模式,大大小小的变化。 柏林噪声函数通过简单地增加了噪声函数在不同尺度范围来再现。


要创建一个Perlin噪声函数,你将需要两个东西,一个噪声函数,插值函数。

噪声函数简介

一个噪声函数基本上是一个种子随机数发生器。 它需要一个整数作为参数,并基于该参数返回一个随机数。 如果你两次相同的参数传递给它,它会产生相同数量的两倍。 这是非常重要的,它在这样的行为,否则柏林函数只会产生废话。


这里有一个图表,显示了一个例子噪声功能。 0和1之间的一个随机值分配给每一个点在X轴。 



由顺利插值之间的值,我们可以定义一个连续函数,需要非整数作为参数。 插值值后,在这篇文章中,我将讨论各种方式。 


定义

之前,我再往前走,让我确定我幅度和频率的意思。 如果你学过物理,你可能遇到的幅度和频率的概念应用到正弦波。

仙波

一种罪过波的波长是从一个高峰到另一个的距离。 振幅波的高度。 频率被定义为1 / 波长 。

噪波

在这个例子噪声功能图,红点表示沿维的功能定义的随机值。 在这种情况下,振幅功能可能的最低和最高值之间的差异。 波长是从一个红点之间的距离。 同样的频率被定义为1 / 波长 。


创建柏林噪声函数


现在,如果你把很多平滑函数,不同频率和振幅,你可以添加它们放在一起,以创建一个漂亮的噪声函数。 这是柏林噪声函数。 
采取以下的噪声函数



加在一起,这是你的。


你可以看到,这个函数有大,中,小的变化。 你甚至可以想像,它看起来有点像山脉。 事实上,许多计算机生成的景观都使用了这种方法。 当然,他们使用2D的噪声,在某一时刻,我就要到。


当然,你可以做2尺寸相同。一些噪音的功能是建立在2D

添加所有这些功能结合在一起,产生一个嘈杂的模式。 

坚持

当你加入这些噪音的功能,你可能不知道究竟什么幅度和频率为每一个使用。 一维上面的例子使用两次的频率和幅度的一半,为每个连续的噪声功能。 这是很常见的。 如此普遍,实际上,很多人甚至不考虑使用别的。 但是,您可以创建具有不同特点的柏林噪声函数通过使用其他的频率和振幅,在每一步。 例如,创造光滑起伏的山峦,你可以使用Perlin噪声函数低频大振幅,更高的频率非常小的振幅。 或者你可以选择低振幅低频率平坦,但非常岩石平面。


使其更简单,并避免重复的话幅度和频率所有的时间,单号是用来指定每个频率的幅度。 这个值被称为持久性 。 有一些含糊之处,它的确切含义。 这个词最初是创造曼德尔布罗分形的发现背后的人之一。 他定义了很多高频噪声具有低持久。 我的朋友Matt也想出了与持久性的概念,但反过来定义。 说实话,我喜欢马特的定义。 对不起曼德尔布罗。 因此,我们的持久性的定义是这样的:


频率= 2振幅=持久


其中 i是第 i个噪声功能被添加。 为了说明柏林噪声的输出效果的持久性,在看看下面的图表。 他们显示添加的组件的噪声功能,持久价值的影响,以及由此产生的Perlin噪声函数。

频率12481632持久性= 1/4

+

+

+

+

+

=

振幅:11/41/161/641/2561/1024导致持久性= 1/2

+

+

+

+

+

=

振幅:11/21/41/81/161/32导致持久性= 1 / root2

+

+

+

+

+

=

振幅:11 / 1.4141/21 / 2.8281/41 / 5.656导致持久性= 1

+

+

+

+

+

=

振幅:111111导致


八度

您添加的每个连续的噪声函数被称为一个八度。 这样做的原因是每一个噪声函数的前一个频率的两倍。 在音乐上,倍频也有此属性。

到底有许多八度加在一起是完全取决于你。 您可以添加尽可能多或尽可能少的,只要你想。 然而,让我给你一些建议。 如果您正在使用Perlin噪声函数呈现在屏幕上的图像,随之而来的一个点时,一个八度有过高的频率是显示。 根本可能没有足够的像素在屏幕上再现一个非常高频率的噪音功能,所有的小细节。 一些柏林噪声实现自动添加了许多噪音功能,他们可以直到屏幕的限制(或其他媒介)达到。

这也是明智的,停止添加噪声功能时,其振幅变得太小重现。 究竟何时发生这种情况取决于持久的水平,在柏林的功能和屏幕的分辨率(或其他)的总幅度。

使你的噪声函数

我们需要什么样的噪声功能? 嗯,它本质上是一个随机数发生器。 然而,不像其他的随机数发生器,您可能会遇到你的节目,给你一个不同的随机数,每次你给他们打电话来,这些噪音的功能,提供一个或多个参数计算一个随机数。 你传递相同数量的噪音功能,即每一次,它会与相同数量的回应。 但它传递一个不同的数字,它会返回一个不同的数字。


好吧,我不知道很多关于随机数发生器,让我去寻找一些,这里是我发现的。 这似乎是相当不错的。 它返回-1.0到1.0之间的浮点数。

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

现在,你想要几个不同的随机数发生器,所以我建议上面的代码中的几个副本,但使用略有不同的数字。 那些大scarey寻找数字都是总理的数字,所以你可以只使用一个同样大小的其他一些素数。 因此,为了使您更容易找到随机数,我已经写了一个小程序来为你列出的素数。 你可以给它一个起始号码和结束号码,就会发现两者之间的所有素数。 源代码也包括在内,所以你可以很容易地纳入自己的程序产生一个随机的素数。 Primes.zip

插值

在创建噪声功能,您将需要理顺的返回值。 再次,你可以选择任何你喜欢的方法,但有些看起来比别人更好。 一个标准的插值函数需要三个输入A和 B的值之间进行插值,x的0和1之间的值。插值函数返回一个值的基础值 x A 和 B 之间 。 当 x等于0时,它返回一个,x为1时,它返回 b。 当 x 0和1之间,它返回A 和 B 之间的某个值。

线性插值:

看起来很糟糕,像那些廉价'plasmas',每个人都使用它来生成景观。 这是一个简单的算法,虽然,我想会是情有可原的,如果你试图做实时Perlin噪声。

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

余弦插值:

这种方法给多少扼杀曲线比直线插补。 这显然&#8203;&#8203;值得努力,如果你能负担得起的速度非常轻微的损失。function Cosine_Interpolate(a, x)
ft = x * 3.1415927
f = (1 - cos(ft)) * .5

return  a*(1-f) + b*f end of function


三次插值: 

此方法提供了非常流畅的效果确实,但你为它付出的速度。 老实说,我不知道是否有更好的结果明显比余弦插值,但在这里它是反正如果你想让它。 这是有点复杂,所以要注意。 而在此之前,插值函数了三个投入,立方插值需要5分钟。 而不是只是A和 B,你现在需要V0,V1,V2和V3 x 之前 ,。 它们是:

V0 =点前

V1 = 点

V2 = B 点

V3 = 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


平滑噪声

除了插值,还可以平滑噪声函数的输出,使看起来不那么随机,也少了在二维和三维版本平方米。 平滑如你所期望,和任何人写的图像平滑滤波器,或火灾算法应该已经熟悉的过程。 

而不是采取简单的噪声函数在一个单一的坐标值,您可以利用该值的平均,和它的邻国值。 如果这是不清楚的,看看下面的伪代码。

在右边,你可以看到一个小图平滑噪声,不平滑的相同的噪音功能之间的差异。 你可以看到,光滑噪声是平坦的,从来没有达到非光滑噪声的极端,出现的频率是大约一半。 有小点平滑一维的噪声,因为这些是真正的唯一的效果。 平滑变得更加有用在2个或3个尺寸,效果,以减少噪音方形。 不幸的是,它也降低了一点对比度。 平滑使其,很明显,噪声就会越平坦。


一维平滑噪声

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

全部放在一起

现在,你知道这一切,是时候把你学到的一切,并创建一个柏林噪声函数。 请记住,这只是几个插值噪声函数叠加在一起。 所以柏林噪声只是一个函数。 传递给它的一个或多个参数,它与数字响应。 所以,在这里是一个简单的一维的柏林功能。

柏林函数的主要部分是循环的。 每个循环迭代中又增加了两倍频率的倍频。 每次迭代调用, 噪音, 表示不同的噪声功能。 现在,你不必实际编写大量的噪音的功能,为每个倍频,伪代码似乎暗示。 由于所有的噪声功能是基本相同的,除了这三个大素数的值,你可以保持相同的代码,但只使用一个素数的每一套不同。

一维柏林噪声伪 &#8203;&#8203;代码

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或更多的三维柏林噪声函数:

2维柏林噪声伪


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) / 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

柏林噪声中的应用

现在你有这样的神奇功能,你可以用它做什么? 嗯,去的陈词滥调,你只限于你的想象力。 柏林噪声有这么多的应用,我不能认为所有这些,但我有一展身手。

一维

控制虚拟众生:

活的对象很少仍然停留很长(学生除外)。 使用Perlin噪声不断调整的一个虚拟的人类球员的共同立场,例如游戏,使它看起来像它更有活力。


绘制勾勒线:

计算机绘制的线条总是完全伸直,这可以使它们看起来不自然的和不友好的。 您可以使用柏林噪声引入到画线算法,使它看起来好像它已经由手工绘制wobblyness。 您还可以绘制的摇晃界和包装盒。 一些研究已经做了一个粗略的用户界面。 
请参阅: 创建非正式展望接口 。




2维

景观:

这是一个完美的应用2D柏林噪声。 细分方法不同,你没有任何地方存储在内存中的景观,景观的高度上任何一点,可以很容易地计算。 更何况,土地的无限延伸(几乎),可以计算出微小的细节,因此它是完美的细节渲染变量水平。 景观的属性可以定义太容易。

有云:

再次,云渲染非常适合于柏林噪声。

生成纹理:

可以使用柏林噪声产生的各种纹理。 一些例子,请参见下表。 生成的纹理,可以去为年龄前重复(如果有的话),这使得他们更加愉快比重复平铺纹理贴图来看看。



3维

三维云:

当然,可以产生体积云。 你可能不得不使用一些排序的射线跟踪可视化。

动画云:

你就可以生产三维柏林噪声动画2维云,如果你考虑一维时间。

固体纹理:

一些渲染/光线追踪程序,如POVray,适用对象纹理字面上从3维纹理雕刻。 这是,纹理不遭受通常与(非平面)3D物体的2D纹理映射到相关的翘曲。



4维

三维动画纹理和云:

移动到更高的层面,你可以轻松地制作动画云和坚实的纹理。 只是考虑额外维度是时间。

@H_502_0@ 总结

以上是内存溢出为你收集整理的Perlin Noise(柏林噪声)全部内容,希望文章能够帮你解决Perlin Noise(柏林噪声)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1279185.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-09
下一篇 2022-06-09

发表评论

登录后才能评论

评论列表(0条)

保存