浅析Minecraft地形生成(二)

前面我们就很频繁地提到了一个词:噪声。并且,我们为了简便起见,在第一章节的维度中实际上并没有使用任何噪声相关的知识,相反,噪声被单独分离了出来,独立一章,足见噪声的复杂性和基础性。

总目录

零 ——

一 —— 新的维度

二 —— 噪声

这一章节中可能不会讲解太多的实际内容,我们更多的会偏向理论一些,讲解Minecraft地形是如何借助噪声算法诞生的。在下一章节中,我们才会讲解噪声在数据包中的应用,即密度函数和噪声设置。

从雪花点开始

首先想想一下我们应该如何生成一个地形。首先确立一个三维坐标系,为了生成一个随机地形,最简单的方式就是,对于每一个x,z值对应的位置,我们直接使用一个随机数作为地形的高度。这样,我们得到的地形大概是这个样子的。

不同的颜色对应不同的地形高度

看起来就像……老电视机上的雪花噪点一样。点与点之间的地形毫无连续性,右边方块的地形可能是y=0,左边可能就变成了y=114的冲天柱子。这显然不是我们想要的地形,那么怎么让地形在有随机性的同时又保留连续性和光滑性呢?

上世纪八十年代,Ken Perlin为了在电影TRON中模拟随机效果,提出了一种随机算法,通过平滑插值的方式,让噪声更加平滑自然。

柏林噪声

可以看出,图像变得平滑了许多,也就意味着我们的地形变得更加的平滑,也就更加趋近于现实。

现在考虑另一个问题。虽然我们现在能生成平滑的噪声,但是噪声太平滑了,很难产生Minecraft世界中需要的各种细节。为了简洁起见,我们用正弦函数的图像来代替我们的噪声函数的起伏:

这是一个简单的y=sinx的函数。和我们的噪声函数一样,平滑,有起伏。但是它也同样不能产生小的细节。现在我们稍微叠加一下:

绿色的还是sinx,橙色的是0.5sin2x,然后我们把这两个函数加起来,得到紫色的函数图像。可以看出来,波峰波谷的基本形状依然是存在的,但是加了一些起伏的小细节。

让我们多加一些类似的函数:

现在是sinx+0.5sin2x+0.25sin4x+0.125sin8x。依然只是简单的叠加,但是看起来和现实中的地形很相似了。如果我们把正弦函数换成柏林噪声,然后进行相同方式的叠加,我们就可以得到有大量细节的地形了!

看起来比单一的柏林噪声有趣多了喵!

数据包中的噪声

数据包的噪声储存在data/<命名空间>/noise/<噪声名称>.json中。它的格式是这样的:

{
   "firstOctave": 整数(一般小于0)
   "amplitudes":[整数列表,一般大于0]
}

wiki似乎缺少这方面的资料,我只能通过自己有限的学识进行一些猜测。firstOctave键大概就是主噪声的频率(周期),amplitudes大概就是设置噪声的振幅,列表则对应了上文中叠加正弦函数一样的叠加过程,而每一个整数值就是要叠加的噪声的振幅,整数值对应的位置则决定了它代表的噪声的频率。例如:

{
  "firstOctave": -5,
  "amplitudes": [
    1,
    1,
    1,
    1,
    1
  ]
}

首先我们决定了噪声的主频率是-5,那么整数列表中从上到下依次五个值,它们对应的噪声倍频则是-5、-4、-3、-2、-1,而振幅则都是1。值得注意的是,实际上叠加的时候的振幅应该是类似1、0.5、0.25的关系。至于为什么会这样做,我也不知道(x

噪声的json文件可能会很费解,但是幸运的是,噪声 生成器 – Minecraft 1.18, 1.19, 1.20 (misode.github.io)可以帮助你实时预览噪声的形状,你只需要大致明白噪声的原理,就可以随心调整参数,直到你满意为止。原版同时也提供了很多写好的噪声函数,你也可以直接调用原版的噪声函数,它们都放在了原版数据包文件夹下对应的位置(和你的数据包一样的位置)

总结

噪声是一切的基础。Minecraft世界生成中,噪声的影子随处可见,地形起伏,生物群系的生成,都离开不了噪声。在下一章中,我们将会继续从噪声出发,讲解噪声是如何生成一个丰富多彩的地形的。

类似文章

发表回复

一条评论