gpt4 book ai didi

math - 用于地形生成的 Perlin 噪声

转载 作者:行者123 更新时间:2023-12-01 15:40:19 28 4
gpt4 key购买 nike

我正在尝试实现 2D Perlin 噪声来创建类似 Minecraft 的地形(Minecraft 实际上并不使用 2D Perlin 噪声)而没有悬垂或洞穴之类的东西。

我这样做的方式是创建一个 [50][20][50] 立方体数组,其中 [20] 将是数组的最大高度,其值将由 Perlin 噪声确定。然后,我将用立方体数组填充该数组。

我一直在阅读 this article我不明白,如何计算 4 梯度向量并在我的代码中使用它?每个相邻的 2D 数组,例如 [2][3] 和 [2][4] 是否有不同的 4 梯度向量?

另外,我读过一般的 Perlin 噪声函数也采用一个数值作为种子,在这种情况下我应该把它放在哪里?

最佳答案

我将使用工作代码来解释 Perlin 噪声,而不依赖于其他解释。首先,您需要一种在 2D 点生成伪随机浮点数的方法。每个点相对于其他点看起来应该是随机的,但诀窍是相同的坐标应该始终产生相同的浮点数。我们可以使用任何散列函数来做到这一点——不仅仅是 Ken Perlin 在他的代码中使用的那个。这是一个:

static float noise2(int x, int y) {
int n = x + y * 57;
n = (n << 13) ^ n;
return (float) (1.0-((n*(n*n*15731+789221)+1376312589)&0x7fffffff)/1073741824.0);
}

我用它来生成一个“风景” landscape[i][j] = noise2(i,j); (然后我将其转换为图像)并且它总是产生相同的东西:

noise noise noise noise ...

但这看起来太随意了——就像山丘和山谷太密集了。我们需要一种将每个随机点“拉伸(stretch)”到 5 点以上的方法。对于那些“关键”点之间的值,你需要一个平滑的渐变:
static float stretchedNoise2(float x_float, float y_float, float stretch) {
// stretch
x_float /= stretch;
y_float /= stretch;
// the whole part of the coordinates
int x = (int) Math.floor(x_float);
int y = (int) Math.floor(y_float);
// the decimal part - how far between the two points yours is
float fractional_X = x_float - x;
float fractional_Y = y_float - y;
// we need to grab the 4x4 nearest points to do cubic interpolation
double[] p = new double[4];
for (int j = 0; j < 4; j++) {
double[] p2 = new double[4];
for (int i = 0; i < 4; i++) {
p2[i] = noise2(x + i - 1, y + j - 1);
}
// interpolate each row
p[j] = cubicInterp(p2, fractional_X);
}
// and interpolate the results each row's interpolation
return (float) cubicInterp(p, fractional_Y);
}
public static double cubicInterp(double[] p, double x) {
return cubicInterp(p[0],p[1],p[2],p[3], x);
}
public static double cubicInterp(double v0, double v1, double v2, double v3, double x) {
double P = (v3 - v2) - (v0 - v1);
double Q = (v0 - v1) - P;
double R = v2 - v0;
double S = v1;
return P * x * x * x + Q * x * x + R * x + S;
}

如果你不了解细节,没关系-我不知道如何 Math.cos()已实现,但我仍然知道它的作用。这个函数给我们带来了拉伸(stretch)、平滑的噪音。

noise -> noise2
stretchedNoise2函数生成一定比例(大或小)的“景观” - 随机点的景观,它们之间具有平滑的斜坡。现在我们可以生成一系列相互叠加的景观:
public static double perlin2(float xx, float yy) {
double noise = 0;
noise += stretchedNoise2(xx, yy, 5) * 1; // sample 1
noise += stretchedNoise2(xx, yy, 13) * 2; // twice as influential

// you can keep repeating different variants of the above lines
// some interesting variants are included below.

return noise / (1+2); // make sure you sum the multipliers above
}

更准确地说,我们得到每个样本点的加权平均值。

( noise2 + 2 * noise3 )/3 = enter image description here

当你将一堆平滑噪声堆叠在一起时,通常是大约 5 个增加“拉伸(stretch)”的样本,你会得到 Perlin 噪声。 (如果你理解最后一句话,你就会理解 Perlin 噪音。)

还有其他更快的实现,因为它们以不同的方式做同样的事情,但是因为它不再是 1983 年,而且因为您开始编写景观生成器,所以您不需要了解所有特殊技巧和术语他们用来理解 Perlin 噪音或用它做有趣的事情。例如:

1) noise 2) noise 3) noise
    // 1
float smearX = interpolatedNoise2(xx, yy, 99) * 99;
float smearY = interpolatedNoise2(xx, yy, 99) * 99;
ret += interpolatedNoise2(xx + smearX, yy + smearY, 13)*1;

// 2
float smearX2 = interpolatedNoise2(xx, yy, 9) * 19;
float smearY2 = interpolatedNoise2(xx, yy, 9) * 19;
ret += interpolatedNoise2(xx + smearX2, yy + smearY2, 13)*1;

// 3
ret += Math.cos( interpolatedNoise2(xx , yy , 5)*4) *1;

关于math - 用于地形生成的 Perlin 噪声,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28755988/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com