现实感十足的2D地形图生成

14
我正在寻找一些算法,可以帮助我生成一个逼真的2D地形图。所谓逼真,是指人们会认为这是一个“正常”的地形图,而不是人工制作的。我不想创建照片般逼真的地图,只需要类似于地理图集中可以查看的地图即可。
到目前为止,我正在使用Perlin噪声来生成高度图,然后添加湖泊、河流、山脉、沼泽等等。你可以看下面图片中的效果。

地形图 http://www.freeimagehosting.net/uploads/1f1e9372bf.png

我对它不满意。它不够逼真,但我自己想不出更好的方法。时间不是问题,因此算法可能需要大量计算。
谢谢你的时间。
编辑后:
我认为我已经找到了一篇有用的文章:http://portal.acm.org/citation.cfm?id=1255047.1255077。然而,它无法免费获取,所以我仍在寻找答案或想法。

4
我找不到我想要的那篇文章了,但基本上它使用了一个以地点为基础的山丘系统来生成漂亮的岛屿。它可能在这里链接:http://pcg.wikidot.com/articles 但我懒得查阅所有的内容。 - Pod
1
你没有说为什么这不现实,具体说明一下你对那些渲染图不满意的地方,是河流、边界、形状等等...我不喜欢绿色和蓝色的比例,太多的绿色没有对比度,而且河流的质量不高...所以至少要增加更多的水域或者一些高度信息,比如海滩、三角洲、山峰等等,还有更多的海岸线。 - bandybabboon
@ufomorace 我所说的“不现实”是指当你看地图时,你会发现山脉、丘陵、河流、平原、草地等一切都以逻辑方式相互连接。我在重构这种逻辑方面遇到了问题。 - Wodzu
@ufomorace,你提出了很多有价值的观点......问题在于,在二维平面上很难展示高度信息,或者如何在山丘上显示森林?这就是为什么我决定将我的渲染切换到三维。首先,我会绘制二维形状,然后对它们进行三角剖分,最后给顶点赋予高度。 - Wodzu
4个回答

6

我以前玩过地形生成。 假设目标是一幅位图,我找到了一种使河流和整体外观更好的方法:侵蚀。

一旦你有了通过其他方式生成的地形,请稍微侵蚀一下:你需要将世界表示为像素高度。 在地图上选择一个点并将一个像素高度向最低邻居移动一次。 将光标移到这个邻居处,重复此操作,直到它不再移动。 对其他像素重复此操作。

要制作河流,请计算通过向下移动位数在某个位置的次数。 被最多击中的点是河流。

跟进: 我并没有侵蚀每个像素,只是简单地侵蚀了大量随机像素,直到它们被侵蚀足够。 实际侵蚀它们的原因是这会将位数向下传递并填补孔洞。 如果没有这个功能,就没有河流,因为会有死亡陷阱阻挡流动-流动像素填满了任何小孔,并产生可行的水路。

很抱歉我无法提供任何样本,这是许多年前的事情,虽然旧代码可能还在某个地方,但我不知道去哪里找。


谢谢Loren。我不确定我是否正确理解了您的意思。我需要侵蚀地图上的每个像素吗?这有点类似于例如从当地山丘的顶部开始,然后向给定方向下降。通过“下降”,我的意思是搜索高度较低或相等的邻居像素。并继续直到条件不被违反。这就是我现在正在做的事情(但我没有降低海拔),您可以看到结果。如果我能看到您的生成器的一些截图,那将是很棒的。 - Wodzu
@Wodzu,我认为Loren的建议是对你有帮助的正确方向。而且你不必侵蚀每个像素;但你应该移动一些(位移它们,沉积物对于形状也很重要)。请参见http://markjstock.org/pages/builder.html上的“erode”图像。 - Unreason

3
地形是由许多不同的原因在许多不同的时间尺度上创建的。要真正创建逼真的地形,您必须模拟这些过程。在“短期”内,水圈决定了大部分特征。您可以从包含主要特征(山脉等)的体素/粒子/高度图/网格地形开始,并将其视为不可变的,然后使用大量的水模拟进行后处理。您需要计算河流和湖泊的位置,它们如何侵蚀基础地貌以及它们形成的沉积物位置。如果我要编写此代码,我可能会从3D体素世界开始。这将是一个巨大的任务,我相信有许多技巧可用于生成特定地形类型,只需花费毫秒而不是几分钟。您想创建什么样的地形?山区?平原?工业化?森林?沙漠?群岛?长话短说:如果您希望地形对人类看起来逼真(毕竟,人类是这方面的专家),则必须通过模拟实际地质过程来创建它。

2
在Terra3D中,我的方法是生成随机高度值,然后进行三次平滑处理,并将一些重塑写入算法中。这种重塑会使水线下的地形向下移动一点,水线以上的地形向上移动一点。但效果是很多山丘和小湖泊。这可能不完全是您想要的。
然而,我并不认为我的方法的原则不能用于实现您想要的结果。您可能需要在重塑/平滑算法中编写更多条件。例如,在较高海拔处减少地形平滑的数量将创建更多岩石山脉的外观。然后编写一个更复杂的平滑(或高斯)算法,以更远的距离延伸到较低的海拔,可以将这些湖泊拉在一起形成自然河流。
以下是Terra3D中地形生成的代码,如果您感兴趣:
  // GENERATE TERRAIN
  for (i = 0; i < MAX; i++)
  {     
    for (i2 = 0; i2 < MAX; i2++)
    {
        if (i<10 || i2<10 || i>MAX-10 || i2>MAX-10)
        field[i][i2].y=0;
      else
        field[i][i2].y=(GLfloat(rand()%151)-75)/50+(field[i-1][i2-1].y+field[i-1][i2].y+field[i-1][i2+1].y+field[i-1][i2-2].y+field[i-1][i2+2].y)/5.05;
    }
  }

  // SMOOTH/RESHAPE TERRAIN
  for (int cnt = 0; cnt < 3; cnt++)
  {  
    for (int t = 1; t < MAX-1; t++)
    {
      for (int t2 = 1; t2 < MAX-1; t2++)
      {
        field[t][t2].y = (field[t+1][t2].y+field[t][t2-1].y+field[t-1][t2].y+field[t][t2+1].y)/4;

        if (cnt == 0)
        {
          if (field[t][t2].y < -1 && field[t][t2].y > -1-.5) field[t][t2].y -= .45, field[t][t2].y *= 2;
          else if (field[t][t2].y > -1 && field[t][t2].y < -1+.5) field[t][t2].y += .5, field[t][t2].y /= 5;
        } 
      }
    }
  }

这是我大约10年前写的糟糕代码。Terra3D是一个漫长的学习过程,通过试验和摸索来产生我所寻找的效果。但也许它会有所帮助。

感谢Steve的关注和代码。我仍在努力完善我的生成器!你的代码非常适合3D飞行模拟器,因为在这种类型的游戏中,用户对于有一些湖泊和山脉感到满意。实际上,他并不太关心地形结构及其逻辑。然而,我正在尝试完成一些不同的事情。如果您打开一个地理相册并查看地形,则会发现它是随机的,但也符合某些规则。例如,河流从山上流向某个湖泊或海洋,或者山脉排列成某些群集。 - Wodzu
此外,从顶部看到的湖泊和山脉(使用2D视图)与地理地图集中的湖泊和山脉相比会显得不够自然。这在3D飞行模拟器中不会被注意到,但在某些战略回合制游戏中会被注意到。再次感谢您的答复。 - Wodzu
@Wodzu - 当然没问题。听起来你已经走得比我远了(我刚注意到这个问题已经几个月了)。显然,有许多细节我没有深入探讨,而你正在积极解决。祝你好运。 - Steve Wortham

1

我知道这是一个非常老的问题,但我正在回答这个问题,为了未来寻找好的地形生成器的人,就像我一样。使用World Machine 2的免费版本。它是一个可以做到你所要求的以及更多的地形生成器。它已经被专业人士用于生成图像、3D世界地形,甚至像你所建议的地图。请注意,免费版本仅供非商业用途。


顺便说一下,网站是www.world-machine.com。 - Felipe M.
免费版在地图大小方面非常有限,并且只会生成一次地图(或者你按“生成”按钮的次数),当你需要一个随机生成的地图时并不是很令人满意 :) - Matěj Zábský
谢谢Felipe M。这个问题虽然旧了,但我仍然对任何帮助感兴趣。我为你的答案点赞,因为你提供的地形生成器可以产生非常漂亮的地形。然而,这个地形仍然没有任何逻辑意义;)好吧,它可以生成一座山和一点水。但它正在生成相同对象的“群集”。湖泊、河流和其他山脉在哪里?这些“对象”必须以自然的方式放置在地图上,就像大自然会做的那样:)例如:河流从山上流向湖泊。 - Wodzu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接