如何使用3d perlin噪声函数生成地形?


20

我可以使用2d perlin杂讯功能来产生高度值,但我不明白为什么要使用3d perlin杂讯功能。在Notch的博客中,http ://notch.tumblr.com/post/3746989361/terrain-generation-part-1,他提到在我的世界上使用3d perlin噪声函数生成地形。有谁知道该怎么做以及为什么会有用吗?如果传递x,y和z值不表示您已经具有高度?

Answers:


19

2D perlin噪声对于高度图很有用,但是在这种情况下,他似乎没有使用高度图。相反,他有一个3D网格,其中任何单元格都可以为空。这允许使用洞穴和此类地层,对于给定的2D位置,地面高度不是单个值。


14

我没有将“地面高度”作为样本,而是将噪声值视为“密度”,其中低于0的任何东西都是空气,高于0的任何东西都是地面。

简而言之,对于可能存在块的每个位置,都会评估噪声函数,如果噪声函数> 0,则会放置一个块。Notch的噪声函数是通过将水位高度增加到其值而偏斜的,这就是为什么较低的区域大部分为实心(高度为负,因此高度+噪声也为负),而较高的区域则大部分为空(高度为正,因此高度+噪声也是正数)。

可能还有一些其他的炼金术来决定生成哪种类型的方块并雕刻洞穴。但是我想这与该噪声功能没有直接关系。

另请注意,此方法适用于Notch,因为Minecraft具有基于体素的地形。如果您试图在基于多边形的世界中实现这一目标,则仅采样噪声函数是不够的。您必须使用某种算法将样本转换为曲面,并创建近似于该曲面的多边形。一种这样的算法是行进立方体


8

如果地形需要洞穴网络和悬垂,则3D噪声成为强制性。

要从密度信息中提取等值面,最流行的两种技术是行进立方体(MC)和较新的双重轮廓(DC)。根据选择的方法,所需的数据结构有很大不同。

如前所述,Geiss的GPU Gems 3文章是了解和在GPU上实现MC地形的非常有启发性的起点(请注意,他的MC方法完全在GPU上运行,并且至少需要具有SM4-GS功能)。

由于MC体素上的密度数据只能保留在体素的边缘上,因此经典MC可能会在不保留尖锐边缘特征的情况下为体积绘制轮廓。DC不会遭受此缺点,因为密度信息表示为3D点(QEF最小化器),该点位于体素内部的任意位置以及每个角处的符号。

另一方面,MC不会出现自相交的面,因为所有生成的三角形均包含在其对应的体素中,而DC需要进行额外的计算以防止生成的面之间发生相交。DC作者在其算法的改进版本中解决了此问题。

http://www.cs.wustl.edu/~taoju/research/interfree_paper_final.pdf

http://www.cs.berkeley.edu/~jrs/meshpapers/SchaeferWarren2.pdf

这位同事还提出了一种基于凸/凹分析的更清洁方法,以避免自相交。他还使用更好的四边形分割规则来帮助保留边的方向:

http://www2.mae.cuhk.edu.hk/~cwang/pubs/TRIntersectionFreeDC.pdf

经典MC也不是开箱即用的“无裂纹”,如果在不受限制的八叉树上运行,可能需要修补裂纹。DC不会受到最后一个问题的困扰。

这是对大多数网格提取技术的相当不错且完整的调查:http : //www.cs.berkeley.edu/~jrs/mesh/

八叉树/体素方法本质上是“ CSG友好”的,这使得计划整齐的,完全“可破坏的”游戏关卡策略更加容易,但是如果需要在游戏中实现所有这些功能,八叉树深度也将变得平淡无奇-依赖。

如果整个内容都适合存储在内存中或已正确传输,则数据也可以用于渲染AO和计算物理/碰撞。


“如果地形需要洞穴网络和悬垂物,则3D噪声变得强制性。” 强制性的吗?如上所示,这是产生洞穴和悬突的唯一方法吗?不。我正在从2D perlin噪波生成一个高度图,然后作为一个单独的步骤雕刻洞穴和悬于其中,以获得更自然的外观。新兴的游戏开发者认为这是在程序生成的世界中产生洞穴和悬垂的唯一方式,这是一种误导。
Domarius'1

5

在该特定示例中,我的猜测是他使用z值来确定哪种类型的材料:基岩,石头,灰尘或空气。


-3

Minecraft使用行进立方体算法生成3D地形。很抱歉,我没有这个参考。我不确定Notch在提到Perlin Noise函数时到底在说什么-也许是行进立方体算法的种子。更多信息在这里:

如果您对行进多维数据集感兴趣,则有一篇很棒的GPU Gems文章:


2
行进立方体是一种用于从标量场生成网格的算法。这意味着它首先需要数据,然后生成网格以适合数据。它不是用于生成数据或地形。
MichaelHouse

-6
for (int x = 0; x < Width) 
{
  for (int y = 0; y < Depth) 
  {
    for (int z = 0; z < Height) 
    {
      if(z < Noise2D(x, y) * Height) 
      {
        Array[x][y][z] = Noise3D(x, y, z)
      } else {
        Array[x][y][z] = 0
      }
    } 
  } 
} 

2
-1; 即使您已经添加了澄清说明,这也是一个很糟糕的答案,它不能清楚地说明代码片段的目的,也不能清楚地解释语义对结果数据的影响,也不能解决用户实际遇到的大多数问题。

我已经编辑了代码,现在呢?
Maxim DC

它解释了如何使用3D噪声制作地形,这在我看来是正确的
Maxim DC

然后在您的答案中进行解释,并解决用户遇到的问题。否则,这是一个死代码答案。
Tom'Blue'Piddock 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.