【问题标题】:Procedural Terrain with ridged fractal noise具有脊形分形噪声的程序地形
【发布时间】:2016-08-16 06:17:16
【问题描述】:

我实现了双线性插值白噪声,以便在程序上生成地形。

我可以得到这样的结果:

我想实现脊形分形噪声以获得更逼真的地形,例如:

但是我找不到关于脊形分形噪声的好教程。你能告诉我怎么做吗?

【问题讨论】:

  • +1 用于包含所需输出的示例 - 当我们都拥有相同的目标图片时,可以更轻松地排除过程故障。说到这一点,看起来可能已经应用了模拟侵蚀来获取输出——你在哪里找到的?
  • 嗨 :) 感谢您的帮助。我认为这是对噪声函数的修改,以便有脊。我认为这是脊形分形噪声。但我找不到我必须对噪音做的改变才能得到这样的东西。在一个网站上,有人告诉它只是用绝对值函数转换的噪声。但我不知道如何使用绝对值函数来改变我的噪声输出:s
  • 我不清楚如何使用绝对值来获得这种效果;不过我听说过using a clamping function to get terraces
  • 只是一个想法,但不是使用直线(双)线性插值,而是在将 x 的值传递给 A * (1 - x) + B 之前应用 sigmoid 类型函数* x 线性插值函数
  • @Pikalek 查看我的回答。我添加了关于如何使用 ABS 函数制作脊的扩展说明。

标签: opengl terrain procedural-generation


【解决方案1】:

脊 perlin 噪声实际上很容易做到 - 您只需 ABS() 最终高度图或噪声层的某个子集(然后反转生成的高度图值,以确保脊出现在高值)。

示例:(具有三线性插值的基本 perlin 噪声,然后是整个高度场的 ABS 和 INVERT)。 (INVERT 表示“乘以 -1”。)

我强烈建议尝试各种分形噪声层配置和基本的数学/逻辑运算。

另一个例子:(两个不同的低频 perlin 噪声层使用逻辑 INTERSECTION / math MINIMUM 函数合并)

但是,对分形噪声算法进行简单的修改不会为您提供那些看起来“下坡”的细节(并使地形更加逼真和吸引人)。要实现这些,您需要添加某种侵蚀模拟,这是一个更复杂的野兽(算法方面和 CPU 方面)。

关于这方面的一些信息,我推荐这两篇论文(你可以忽略 GPU 部分,算法在 CPU 上运行良好,尽管根据我的经验,对于 1000x1000 像素的图像,模拟需要一分钟左右):

  1. Mei, Xing, Decaudin, Philippe and Hu, Bao-Gang. Fast Hydraulic Erosion Simulation and Visualisation on GPU. 2007.
  2. Fast Hydraulic and Thermal Erosion on the GPU. Jákó, Balász. 2011. The 15th Central European Seminar on Computer Graphics.

编辑:

让我们澄清一下我所说的“在高度场上应用 ABS”的意思。

您只需在地图的每个像素中获取高度的数值并对其应用 ABS () 函数,丢弃其符号。

假设 perlin 噪声生成器生成范围 (或以 0 为中心的另一个范围)中的值。预计约 50% 的像素值大于 0,预计约 50% 的值小于 0。

ABS 会导致在 0 处创建尖锐的脊,因为所有双线性/三线性插值都会确保曾经有一个平滑的斜率通过 0 值。

考虑这张图片:

它显示了两个 COS(x) 函数,其中一个是用 ABS 函数调制的(我添加了一个小的偏移量以确保两条线分别可见)。现在想象一下,紫色的线是垂直翻转的——你最终会看到两座山峰,山脊尖锐,中间有一个山谷:)

【讨论】:

  • 最后一次编辑让我明白了。我一直对我的噪声值进行归一化 - 显然在归一化数据上运行 ABS 不会改变它,这就是为什么我看不到如何将 ABS 应用于这种情况。这为我开辟了一些有趣的新选择。
  • @Pikalek 是的,如果你想深入了解程序地形生成,学习以各种方式思考地图真的很有帮助——它们可以是灰度图像、3D 模型、数学函数、法线场、一维函数序列、层堆栈、体素模型——每一个都有其优点和局限性,尤其是在修改和组合它们的方式上。
  • 非常感谢,现在看起来更全面了。但是我不明白在 ABS 之后 INVERT 的目的。如果你能突出显示我会很好:)
  • @JimZer 反转我的意思是“将每个值乘以 -1”。如果您在我的回复中查看图中的紫色线,您会看到尖峰(脊)指向下方。您希望它们指向上方,因此它们是山脉,因此您将整个高度场乘以 -1。
  • 超级!我现在真的明白了;)非常感谢。您能否提供一些很好的资源来更深入地进行程序地形生成,我真的很感兴趣。
【解决方案2】:

为了产生物理上逼真的脊,修改噪声函数,如前面的答案所述,可能不是最好的方法。相反,如果您从分形表面开始,并对其应用适当的侵蚀函数,则可以相当轻松地创建具有物理逼真形状的山脊。

我最近在我的网站上写下了我的努力:https://fractal-landscapes.co.uk/maths.html

基本上,如果您的目标只是山脊,您可以修改热侵蚀方程以消除所有沉积物(即仅进行减法侵蚀)。我包括了我用来侵蚀一个点的 C# 代码 - 它相当快,并且会在我的 PC 上以大约 10 秒的时间进行 250 次迭代,从而侵蚀我的 4096x4096 测试环境(尽管在 12 个内核上进行了一些并行化)。

搞乱位只是获取被侵蚀点的 8 个相邻点的有效方法 - 我的表示使用线性数组,因此 y 坐标预先乘以景观的宽度(yMul 等...)。为简单起见,您可以将 stride 视为 1。 r2demon 和位移位只是角点乘以 1/sqrt(2) 的快速乘法。

var x0 = (x1 - stride) & mask;
var x2 = (x1 + stride) & mask;
indices[0] = x0 + yMul0;
indices[1] = x1 + yMul0;
indices[2] = x2 + yMul0;
indices[3] = x0 + yMul1;
indices[4] = x2 + yMul1;
indices[5] = x0 + yMul2;
indices[6] = x1 + yMul2;
indices[7] = x2 + yMul2;

for (int i = 0; i < actualLength; i++)
{
    elements[i] = thisSurface[indices[i]];
}

var height = thisSurface[x1 + yMul1];

//Differences in height.
//Corner differences multipled by 1/sqrt(2)
diffs[0] = ((height - elements[0]) * r2denom) >> 8;
diffs[1] = height - elements[1];
diffs[2] = ((height - elements[2]) * r2denom) >> 8;
diffs[3] = height - elements[3];
diffs[4] = height - elements[4];
diffs[5] = ((height - elements[5]) * r2denom) >> 8;
diffs[6] = height - elements[6];
diffs[7] = ((height - elements[7]) * r2denom) >> 8;

//Compare the differences to the talus threshold.
var max = 0;
var talusSum = 0;
var slopeSum = 0;
for (var i = 0; i < actualLength; i++)
{
    var diff = diffs[i];
    if (diff > 0)
    {
        if (diff > max)
        {
            max = diff;
        }

        talusSum += diff;
        if (diff > talusThreshold)
        {
            slopeSum += (diff - talusThreshold);
        }
    }
}

talusSum = talusSum / 2 - talusThreshold;

if (talusSum > 0)
{
    //Work out how much height to redistribute.
    var toMove = talusSum / 4;
    if (altitudeProportional)
    {
        toMove *= (height - minAltitude);
        toMove /= (maxAltitude - minAltitude);
    }

    newSurface[x1 + yMul1] -= toMove;
}

【讨论】:

  • 此链接上的信息非常酷!虽然原始帖子很旧,但我希望以后访问此链接的任何人仍然可以找到有用的答案!但是,我经常使用噪音,而且我对您文章中的某些单词选择存在分歧。具体来说,它与“生成广泛使用的分形表面的主要方法有两种:位移噪声(此处描述)和梯度噪声(其中最好的例子是 Perlin 噪声)”这一行有关。
  • 我绝对不认为 Perlin 是梯度噪声的最佳例子,甚至不是一个值得强调的好例子。就个人而言,我会用对 Simplex 和/或 Simplex-related 噪声的引用来替换它。 Perlin 是一种较旧且视觉上非常各向异性的噪声函数。它可能不像您在各向异性部分中介绍的 Diamond-Square 算法那样明显,但偏差很明显。我很少看到一个项目使用 Perlin 来处理与 Simplex 相关的噪音,而且看起来效果更好。
  • 继续把焦点放在 Perlin 上可能对 PCG 的新人有害,他们已经听说过 Perlin 比什么都多。我更喜欢诸如“一个值得注意的例子是单纯形噪声”或“例子包括单纯形或 Perlin 噪声”之类的短语(如果您也需要参考,请不要将 Perlin 放在列表中)
  • 这样,读者就不会因为你的方法的最佳替代方案是 Perlin 噪声而退出。
  • 谢谢。关于单纯形噪声的观点,尽管与一般的梯度噪声一样,它会受到位移函数中周期性零点的影响。
猜你喜欢
  • 2014-06-14
  • 2011-06-12
  • 2011-09-20
  • 2015-09-15
  • 1970-01-01
  • 1970-01-01
  • 2018-10-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多