如何为地图生成创建平铺的固体噪声?


16

大家好,我试图弄清楚如何在代码中生成可分割的分形(对于游戏地图,但这无关紧要)。我一直在尝试修改GIMP附带的Solid Noise插件(我对如何该代码有效),但我无法让我正常工作。

到目前为止,我修改过的代码(Java)

GIMP的固体噪声模块,我的代码基于(C)

这是我想要实现的目标,但这 就是我得到的目标

因此,如果任何人都可以看到我做错了什么,或者有建议我可以做些不同的事情,我将不胜感激。提前致谢。 如果我要问的是很多事情,或者是人生中的巨大失败,我深表歉意。


尝试使用双三次插值而不是双线性?我不知道这是否是您的问题,但看起来确实如此。
Stephen Furlani 2010年

Answers:


4

我没有完全遵循您的代码,但这是对将大致实现此效果的算法的简化描述(基于您发布的图像)。

以下说明不是超级优化的版本,但在概念上很明确(我希望如此)。一旦运行它,就可以对其进行优化(实际上,这是非常大的)。

  1. 生成n层均匀的随机噪声(仅随机灰度像素)。
  2. 现在,通过对每个1、2、4、8,... 2 ^(n-1)个像素进行采样并对中间像素进行插值来对每个像素进行采样。每层都比前一层平滑。
  3. 现在以1、2、4、8等倍数缩放这些图层。每一层都比上一层更暗。
  4. 将所有这些加在一起。
  5. 通过将每个像素除以(1 + 2 + 4 + 8 + ... 2 ^(n-1))进行归一化。

困难的步骤是采样和内插步骤。假设我们在该层中跳过每第m个像素的采样。这是m> 1的基本思想(如果m为1,则按原样使用图像):

for each pixel x and y
   left_sample_coord = m *(x / m) //(integer division, automatically truncated)
   right_sample_coord = (left_sample_point + m) % image_width
   top_sample_point = m*(y / m) 
   bottom_sample_coord = (top_sample_point + m) % image_height

   horizontal_weight = (x - left_sample_point) / (m - 1)
   vertical_weight = (y - top_sample_point) / (m - 1)

   sample_top_left = image(left_sample_coord, top_sample_point)
   //and the same for the other four corners

   //now combine the top two points
   top_interpolate = sample_top_left * horizontal_weight + sample_top_right * (1-horizontal_weight)

  //now combine the bottom two points
  bottom_interpolate = sample_bottom_left * horizontal_weight + sample_bottom_right * (1-horizontal_weight)

  //and combine these two last obtained values

  smooth_noise(x, y) = top_interpolate * vertical_weight  + bottom_interpolate * (1 - vertical_weight)

一些提示:

  • 上面算法的结果似乎有点被淘汰了。您可以通过对所有层使用相同的噪点层来减少这种影响,或者之后可以对比增强图像。
  • 上面的算法使用线性插值,但是余弦插值(执行搜索)会提供更好的结果。
  • 使在算法的所有部分中分别查看图层成为可能。这将帮助您快速清除错误。

3

似乎我的原始pastebin某种程度上已经过期了,所以我无法比较我的无效代码,但是在我当前的游戏中,我经历了一次并将GIMP代码再次转换为Java的方法,现在看来可以正常工作了。

如果有人打算使用此代码,我建议您修改构造函数以修改设置参数(详细信息和大小),以便使其按您希望的方式工作。编辑:我意识到我最初的问题是关于使其可平铺,所以请记住将tilable设置为true!

程式码:http//pastebin.com/KsfZ99Xa

例: 佩林发生器示例


2

刚刚浏览了Java和C版本,发现使用noise函数的方式略有不同。这是你的:

int val = Math.abs((int) Math.floor(255.0 * noise(((double)col/(double)width), ((double)row/(double)height))));

C代码:

val = (guchar) floor (255.0 * noise ((col - xoffset) / width,

                                           (row - yoffset) / height));

为什么选择不减去偏移量?(col-xoffset)和(row-yoffset)

就是想。我没有时间对代码进行全面分析。

希望这可以帮助。


xoffset和yoffset是以GIMP将图像划分为网格的方式计算的,但是我的程序都在一个图块上工作,因此x和y的偏移量将为0
Nick Badal 2010年

2

我不知道是否有帮助,但是以下技巧对我有效:

http://www.gamedev.net/blog/33/entry-2138456-seamless-noise/

这位同事正在使用4d噪声函数,并简单地提供两个圆的xy值作为4d噪声的xyzw值。结果是完美的循环。

这是1000 * 1000图片的想法(简化):

for(i = 0;i < 1000; i++){

  for(j = 0; j < 1000; j++){

    nx = cos((i/1000) * 2 * PI);
    ny = cos((j/1000) * 2 * PI);
    nz = sin((i/1000) * 2 * PI);
    nw = sin((j/1000) * 2 * PI);

    looped_noise = noise_4D( nx, ny, nz, nw, octaves, persistence, lacunarity, blah...);
    noise_buffer[(i*1000)+j] = looped_noise;

  }
}

1

我建议您使用菱形平方算法,也称为等离子分形或随机中点位移分形。使用此算法很容易将边缘约束为相同的值。生成边的值时,请将其复制到另一边的相应边上。这将产生一个完美的平铺贴图。


0

有一个关于噪音的产生一个伟大的文章在这里。这不是本文所说的Perlin噪声(实际上是粉红噪声),但了解如何生成噪声图像仍然非常有用。

因此,要实际回答您的问题:要制作可平铺的噪声图像,您只需要在整个过程中保持“可调整性”即可。也就是说,当对噪声进行平滑处理时,就可以平滑它,就好像它在所有方向上无限重复一样-平铺。


0

从屏幕截图中,我猜测是仅生成“大”图层,这就是为什么噪声显得过于规则且缺乏细节的原因。

这听起来可能很愚蠢,但是您是否尝试增加“详细信息”变量(第16行)?在您的代码中,它设置为1,这意味着算法在停止之前只会生成两层细节。尝试将其增加到大约8。


0

您还应该看看Simplex Noise,它是Ken Perlin开发的,用于解决Perlin noise的一些缺点。

我一直在为C ++游戏实现Simplex Noise。它支持多倍频程1D / 2D / 3D / 4D噪声。目前,唯一的内置纹理是大理石,但是您可以轻松添加更多:

(http://code.google.com/p/battlestar-tux/source/browse/trunk/src/lib/procedural/)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.