地形生成-在多个生物群落高度图之间进行插值

时间:2018-10-18 16:13:33

标签: c# voronoi perlin-noise procedural-generation heightmap

最近我已经使用统一引擎和C#进行了一些地形生成,我能够克服我遇到的大多数问题,但是这个问题使我陷入困境,而没有有效的解决方案:

因此,在我解释我的问题之前,我将解释到目前为止的成就。通过使用perlin噪声,我已经能够生成网格并通过组合多个高度图将不同的高度应用于其顶点。我还能够生成和销毁地形块,以及基于查看器的位置管理块的LOD(出于优化目的)。接下来,我参加了生物群落区域分布系统,对于区域分布,我使用了代表温度和湿度水平的2个perlin噪声函数与voronoi细胞分布的组合,通过一些模将世界划分为虚拟正方形,而另一个perlin噪声函数是用来创建一个函数,该函数基于它接收到的虚拟平方作为输入返回一个voronoi控制点,到目前为止,我想到的只是一个voronoi控制点分布算法,到目前为止效果很好...

接下来,我想让地形变得更有趣(它是为生存游戏而设计的),所以我开始为每个生物群系(每个voronoi细胞)具有独特的噪声功能组合而努力,但这并不是那样容易...生物群落之间的接缝一定会开始显示出来,因此需要一个生物群落插值系统,首先我认为一个简单的权重函数就可以完成工作,这意味着每个顶点都要计算其与相邻生物群落细胞的距离并计算权重每个单元在该顶点上都有一个值:0到1之间的值,0 =最低影响(生物群系点确实很远,对顶点没有任何影响); 1 =最高效果(生物群系点与顶点的位置完全相同,因此,它将对顶点的高度产生最大影响,并且将完全由生物群系的独特噪声函数合成),然后计算每个相乘的总和生物群落在顶点上的权重由其顶点位置上生物群落噪声函数决定(注意:所有生物群落点权重的总和应始终为1)。

相邻点的权重计算示例:

An example of weight calculation for adjacent points

在图片中: 蓝色箭头所指的生物群落的重量约为0.1f(此值很小,因为它距采样点很远,因此对采样点的高度影响很小)。 绿色箭头所指的生物群落的重量约为0.45f。 粉色箭头指出的生物群落的重量约为0.45f(与绿色指出的生物群落相同,因为它与采样点的距离相同)。 橙色点=将根据其得出权重的样本点。

有一类使用噪声的算法,称为细胞噪声,它是一种voronoi分布,与我正在寻找的相似,但是没有考虑其他相邻生物群落对最终值的影响,这意味着离任何生物群落控制点的最低点将是最低的,但是它没有融合不同的生物群落,这对我来说是必须的,我希望我很好地解释了该算法的问题。无论如何,这是一个例子。

蜂窝噪声高度图的示例:

An example of Cellular noise heightmap

一小段代码可以确定最终顶点的高度:

float HeightAtPosition(float x, float z)
{
    //Returns an array containing information of all the adjacent biome 
    //control points(mainly their position and their biome type)
    BiomeControlPoint[] adjacentControlPoints = GetAdjacentBiomePoints(x, z);
    //Returns an array containing values between 0 and 1
    //Iputs: An array of all the adjacent biome points, a sample coordinate
    //Output: A float array containing the weight of each biome on the 
    //        coordinate(between 0 and 1)
    float[] weights = CalcWeights(adjacentControlPoints, new Vector2(x, z));
    float finalHeight = 0;
    for (int i = 0; i < adjacentControlPoints.Length; i++)
    {
        finalHeight += adjacentControlPoints[i] * weights[i];
    }
    return finalHeight;
}

如果我可以提高这些功能的性能效率,这将是一个很好的解决方案: GetAdjacentBiomePoints(x,z) 和 CalcWeights(adjacentControlPoints,new Vector2(x,z))

我读过的另一种方法是双线性插值,但我不太了解它的实现,因此我很乐意向其他人士学习。 该视频讨论了这种方法:https://www.youtube.com/watch?v=ujGW5y1x7Jg Creating Minecraft in C++/ OpenGL - Part Four

很高兴向您学习任何新的信息和/或想法:) 预先谢谢你!

2 个答案:

答案 0 :(得分:0)

您可以尝试加权voronoi图。我的php实现:https://tetramatrix.github.io/awvd/

答案 1 :(得分:0)

您可以选择另一种方式:

  • 为每个像素生成温度和湿度水平
  • 生成每个生物群系与这些值匹配的数量
    • 将每个生物群落的强度预先计算为二维查找表?
  • 参加X场最佳比赛
  • 标准化强度(总和为1)
  • 您独特的噪声功能组合是X个最佳生物群落的加权总和

我个人使用网格图,并将生物群系的值从具有大单元格的小地图插入到具有小单元格的大地图。插值在这里容易得多:

对不起,它是java。