Minecraft terrain generation in a nutshell

[熟肉]Minecraft的地形是如何生成的?_我的世界

Minecraft 在本文简称麦块。

评价

总的说,这个视频没有太多数学公式,基本上是代码、视频切片组成,也没有讲得特别细,但是最重要的已经讲了。

也就是柏林噪声在麦块中的使用,柏林噪声如何决定麦块的地形生成。像是叠加、倍频,还有3d噪声生成洞窟和悬空山崖的办法。

摘记

麦块的地形生成

懒得记。

简单说,麦块的地形是随着跑图而进行生成的。挺好理解,因为麦块的世界非常大,不可能全部生成并存储下来,而是通过记住种子并利用种子随着玩家跑图加载未生成过的区块来进行生成。

麦块的地形生成是以区块为单位进行生成的。

由此引出地形生成的问题的建模,其可以简单地表示成问题:这个位置应该放什么方块?

即已知位置坐标,算这个位置坐标的方块。

地形生成可以分为几步骤。

  1. 计算哪些是固体方块,哪些是空气。
  2. 在海平面下的空气填充水。
  3. 把顶层方块更换为草方块和沙子。
  4. 添加地物和结构。

这个视频重点讲解第一步。

使用噪声生成地形

中间有几个简单的版本迭代,但是我懒得详细记。

用2d柏林噪声来决定一个高度浮动,然后将浮动加在一个固定的高度上,就可以得到一定范围内的随机高度,同时具有柏林噪声平滑连续的特点。

BlockState GetBlock(int x, int y, int z) {
	PerlinNoise noise = new PerlinNoise();
	var surfaceY = 100 + noise.sample2d(x, z) * 20;
	return (y < surfaceY) ? STONE : AIR;
}

倍频技巧:将多个噪声叠加

虽然地形已经有了变化,但是可以更进一步,使用名为倍频 octaves的技巧,将不同倍频的柏林噪声叠加在一起,达到在总体上遵循低频柏林噪声,在局部上遵循另一个高频柏林噪声的效果。

一般叠加的配置是倍频多一次,频率就跟着翻一倍,振幅减少1/2。

BlockState GetBlock(int x, int y, int z) {
	final int octaves = 4;
	PerlinNoise noise = new PerlinNoise();
	var surfaceY = 100 + noise.sample2d(x, z) * 20;
	return (y < surfaceY) ? STONE : AIR;
}

使用噪声对噪声进行变化

尽管引入了倍频,但是倍频无法生成陡峭的山峰和悬崖。

为此回顾生成过程,可以在取得柏林噪声值后对噪声值转换成地形高度的地方做手脚。

定义一个大陆值 continentalness,以大陆值作为子标量,地形高度作为因变量。

本质上就是,同时f是设定的简单线性分段函数,地形高度就是之前前文说的高度值

像这样在中间过程对高度等各个方面进行变化的噪声图还有很多,比如说侵蚀度以及河流度之类的。

三维柏林噪声、悬空山崖与洞窟生成

悬空山崖的生成

三维的柏林噪声输出的值可以看作密度 density。可以通过将低密度值的地方填充空气,高密度值的地方填充固体方块。

我真服了这b作者不喜欢写公式是吧。

懒得写了,大概就是决定是空气还是固体的密度范围随高度变化,足够低的地方全是固体方块,足够高的地方全是空气,中间则是根据密度范围的大小呈现出不同的特色。

所以可以调整的就是密度范围大小——也就是挤压值,还有高度变化——也叫高度偏移

洞窟的生成

3d 柏林噪声还能生成洞窟。

生物群系与柏林噪声

决定生物群系的也是像刚才前文那种多个柏林噪声进行决定的,取决于温度湿度奇异性山脊度等等。

更复杂的还要考虑生物群系的相邻问题。