更改 Perlin 噪声算法以使用连续程序生成
Change Perlin noise algorithm to work with continuous procedural generation
现在我有一个 perlin 噪声函数,我在其中传递种子缓冲区和函数填充噪声值的另一个缓冲区。我正在使用它来按程序生成地形中顶点的高度。现在的问题是地形仅限于缓冲区的大小,但我想让它连续生成块,这些块彼此一致,但我不知道如何使用我正在使用的当前函数来做到这一点。这是算法的代码,有什么我可以更改以使其工作的吗?
inline void perlInNoise2D(int nWidth,int nHeight, float *Seed, int nOctaves, float fBias, float *fOutput)
{
for(int x = 0; x < nWidth; x++)
{
for(int y = 0; y < nHeight; y++)
{
float fNoise = 0.0f;
float fScale = 1.0f;
float fScaleAccum = 0.0f;
for(int o = 0; o < nOctaves;o++)
{
int nPitch = nWidth >> o;
int sampleX1 = (x / nPitch) * nPitch;
int sampleY1 = (y / nPitch) * nPitch;
int sampleX2 = (sampleX1 + nPitch) % nWidth;
int sampleY2 = (sampleY1 + nPitch) % nWidth;
float fBlendX = (float)(x - sampleX1) / (float) nPitch;
float fBlendY = (float)(y - sampleY1) / (float) nPitch;
float fSampleT = (1.0f - fBlendX) * Seed[sampleY1 * nWidth + sampleX1] + fBlendX * Seed[sampleY1 * nWidth + sampleX2];
float fSampleB = (1.0f - fBlendX) * Seed[sampleY2 * nWidth + sampleX1] + fBlendX * Seed[sampleY2 * nWidth + sampleX2];
fNoise += (fBlendY * (fSampleB - fSampleT) + fSampleT) * fScale;
fScaleAccum += fScale;
fScale = fScale / fBias;
}
fOutput[(y * nWidth) + x] = fNoise / fScaleAccum;
}
}
}
大概这与“地图显示”机制有关?
一种常见的技术是生成重叠块并将它们平均在一起。作为一个简单的示例,您通过 2*nHeight
生成 2*nWidth
的块。然后你在任何 XY 位置都有 4 个重叠的块。在地图的边缘,您将看到一条条带,其中并未生成所有块。当需要显示地图的这一部分时,您可以即时生成这些块。这会将边缘向外移动。
平均过程已经消除了边界效应。您可以通过平滑其边缘附近的每个单独块来使其更有效。由于块边缘不重合,不同块的平滑也不重合。一个简单的三角形平滑就足够了(即平滑 window 在中间是 1,在边缘是 0,在中间是线性的)但是你也可以使用高斯或任何其他在中间达到峰值并逐渐增加的函数向块边缘平滑。
现在我有一个 perlin 噪声函数,我在其中传递种子缓冲区和函数填充噪声值的另一个缓冲区。我正在使用它来按程序生成地形中顶点的高度。现在的问题是地形仅限于缓冲区的大小,但我想让它连续生成块,这些块彼此一致,但我不知道如何使用我正在使用的当前函数来做到这一点。这是算法的代码,有什么我可以更改以使其工作的吗?
inline void perlInNoise2D(int nWidth,int nHeight, float *Seed, int nOctaves, float fBias, float *fOutput)
{
for(int x = 0; x < nWidth; x++)
{
for(int y = 0; y < nHeight; y++)
{
float fNoise = 0.0f;
float fScale = 1.0f;
float fScaleAccum = 0.0f;
for(int o = 0; o < nOctaves;o++)
{
int nPitch = nWidth >> o;
int sampleX1 = (x / nPitch) * nPitch;
int sampleY1 = (y / nPitch) * nPitch;
int sampleX2 = (sampleX1 + nPitch) % nWidth;
int sampleY2 = (sampleY1 + nPitch) % nWidth;
float fBlendX = (float)(x - sampleX1) / (float) nPitch;
float fBlendY = (float)(y - sampleY1) / (float) nPitch;
float fSampleT = (1.0f - fBlendX) * Seed[sampleY1 * nWidth + sampleX1] + fBlendX * Seed[sampleY1 * nWidth + sampleX2];
float fSampleB = (1.0f - fBlendX) * Seed[sampleY2 * nWidth + sampleX1] + fBlendX * Seed[sampleY2 * nWidth + sampleX2];
fNoise += (fBlendY * (fSampleB - fSampleT) + fSampleT) * fScale;
fScaleAccum += fScale;
fScale = fScale / fBias;
}
fOutput[(y * nWidth) + x] = fNoise / fScaleAccum;
}
}
}
大概这与“地图显示”机制有关?
一种常见的技术是生成重叠块并将它们平均在一起。作为一个简单的示例,您通过 2*nHeight
生成 2*nWidth
的块。然后你在任何 XY 位置都有 4 个重叠的块。在地图的边缘,您将看到一条条带,其中并未生成所有块。当需要显示地图的这一部分时,您可以即时生成这些块。这会将边缘向外移动。
平均过程已经消除了边界效应。您可以通过平滑其边缘附近的每个单独块来使其更有效。由于块边缘不重合,不同块的平滑也不重合。一个简单的三角形平滑就足够了(即平滑 window 在中间是 1,在边缘是 0,在中间是线性的)但是你也可以使用高斯或任何其他在中间达到峰值并逐渐增加的函数向块边缘平滑。