12

I'm working with Perlin Noise for a height map generation algorithm, I would like to make it wrap around edges so that it can been seen as continuous.. is there a simple way or trick to do that? I guess I need something like a spherical noise so that either horizontally and vertically it wraps around. I would be happy also with just 1 wrapping axis but two would be better.

For now I'm using the classical algorithm in which you can set up how many octaves you want to add and which are the multipliers used for changing amplitude and frequency of the waves between every successive octave.

Thanks in advance!

Jack
  • 131,802
  • 30
  • 241
  • 343
  • You don't happen to be trying to build periodic minecraft worlds, are you? :D – Cephron Apr 07 '11 at 21:38
  • Of course I'm not trying to do it, although I knew someone would have told it :) (then it's also 2D not 3D) – Jack Apr 07 '11 at 22:42

1 Answers1

8

Perlin noise is obtained as the sum of waveforms. The waveforms are obtained by interpolating random values, and the higher octave waveforms have smaller scaling factors whereas the interpolated random values are nearer to each other. To make this wrap around, you just need to properly interpolate around the y- and x-axes in the usual toroidal fashion, i.e. if your X-axis spans from x_min to x_max, and the leftmost random point (which is being interpolated) is at x0 and the rightmost at x1 (x_min < x0 < x1 < x_max), the value for the interpolated pixels right to x1 and left from x0 are obtained by interpolating from x1 to x0 (wrapping around the edges).

Here pseudocode for one of the octaves using linear interpolation. This assumes a 256 x 256 matrix where the Perlin noise grid size is a power of two pixels... just to make it readable. Imagine e.g. size==16:

 wrappable_perlin_octave(grid, size):
   for (x=0;x<256;x+=size):
     for (y=0;y<256;y+=size):
       grid[x][y] = random()
   for (x=0;x<256;x+=size):
     for (y=0;y<256;y+=size):
       if (x % size != 0 || y % size != 0): # interpolate
         ax = x - x % size
         bx = (ax + size) % 256 # wrap-around
         ay = y - y % size
         by = (ay + size) % 256 # wrap-around
         h = (x % size) / size # horizontal balance, floating-point calculation
         v = (y % size) / size # vertical balance, floating-point calculation
         grid[x][y] = grid[ax][ay] * (1-h) * (1-v) +
                      grid[bx][ay] * h * (1-v) +
                      grid[ax][by] * (1-h) * v +
                      grid[bx][by] * h * v
Antti Huima
  • 25,136
  • 3
  • 52
  • 71
  • 1
    I found this information to be similarly helpful: http://webstaff.itn.liu.se/~stegu/TNM022-2005/perlinnoiselinks/perlin-noise-math-faq.html#toc-tile – David Braun Jun 07 '14 at 18:16
  • I think this suffers from "muddling" artifacts in the middle of each Perlin grid cell as described here: http://www.gamedev.net/blog/33/entry-2138456-seamless-noise/ and here: http://staffwww.itn.liu.se/~stegu/TNM022-2005/perlinnoiselinks/. (The first link also describes a better solution.) – Leftium Sep 08 '15 at 11:43
  • 2
    The answer above does not make sense, because the second loop goes in steps of `size`, and then the modulo calculation must be zero at every step. So the main calculation is never been called! – Alex Nov 10 '15 at 08:10