无限高清远视距地形生成: 超越无人深空和Minecraft

最近我使用虚幻引擎和其shader plugin开发了一个可以生成无限体素(voxel)地形的项目。因为项目仍未完成,我把代码放置在github上,希望大家能够给星并关注: https://github.com/MarchingVoxels/Smooth-Infinite-Voxel-Terrain

以下是目前项目的截图(以下的低多边形效果是通过shader故意添加的效果,并非因为此项目不支持平滑阴影):

无限高清远视距地形生成: 超越无人深空和Minecraft

无限高清远视距地形生成: 超越无人深空和Minecraft

可以看到,植被与多边几何的发现对其。材质的颜色则通过用法线计算两种颜色的插值获得。

第二张图中可以看到及其远的视距(如果去掉多变效果会是平滑的)

生成地形时,我没有使用minecraft或无人深空中的放置算法,即通过创建二维的单元格并做圆周计算判断是否放置地形区块。

在此项目中,我使用八叉树将空间递归切分。离玩家越远则八叉树的叶体积越大:

无限高清远视距地形生成: 超越无人深空和Minecraft

在八叉树将地形分割完成后,就可以用地形区块填充八叉树的叶,并分别通过叶距离玩家的距离来计算几何细节程度(level of detail),使离玩家越远的地形几何体数量越小,保障极其远的视距,良好的视觉效果和无卡顿。

现在我们要讨论地形区块视觉化的细节。我们可以用柏林噪音生成基本的地形形状。此项目使用了三维柏林噪音生成地表悬垂岩和地下洞穴,用二维噪音生成温度,湿度,盐度信息和基本地形形状。

此项目使用一种高性能的柏林噪音,simplex noise。以下是simplex noise的基本语法:

float simplex_noise(float x, float y, float z);//三维

float simplex_noise(float x, float y);//二维

应该用不同的方式理解三维和二维噪音函数。在地形生成中,三维函数应该用如下方式去生成地形:

for(int x = 0; x < chunk_width; x++)

    for(int y = 0; y < chunk_height; y++)

        for(int z = 0; z < chunk_depth; z++)

            chunk[x][y][z] = (simplex_noise(x * freq, y * freq, z * freq) < threshold;

        end

    end

end

而二维噪音函数则生成地形的基本结构。因此,用二维噪音生成高度图最为合适。以下是二维噪音函数生成的高度图(由黑至白从低变高):

无限高清远视距地形生成: 超越无人深空和Minecraft

我们可以将很多独立的二维噪音函数叠加在一起,形成复杂的图案:

float octave_one = simplex_noise(x * freq1, y * freq1, z * freq1);

float octave_two = simplex_noise(x * freq2, y * freq2, z * freq2);

float octave_three = simplex_noise(x * freq3, y * freq3, z * freq3);

combined_noise = octave_one + octave_two + octave_three;

如果threshold设置正确的话,就可以结合二维和三维噪音图生成多种多样的地形。以下是在二维噪音的平面上生成三维悬垂岩的效果(老版本,因此是方形):

无限高清远视距地形生成: 超越无人深空和Minecraft

使用虚幻引擎的math::abs生成噪音图的绝对值,可以得到弯曲的噪音图案,得到河流的效果:

无限高清远视距地形生成: 超越无人深空和Minecraft

明天我会更新平滑地形的部分。