

   int i;
   double val,sum = 0;
   double p[2],scale = 1;

   p[0] = x;
   p[1] = y;
      val = noise2(p);
      sum += val / scale;
      scale *= alpha;
      p[0] *= beta;
      p[1] *= beta;

Using code like:



Gives sky like


Which isn't tileable.


How can I make it tileable?

  • 14
    \$\begingroup\$ Just FYI, what you have there isn't Perlin noise; it's fractal noise. Perlin noise is likely the "noise2" function generating each octave of the fractal noise. \$\endgroup\$ – Nathan Reed Feb 10 '12 at 6:49

10 Answers 10



import random
import math
from PIL import Image

perm = range(256)
perm += perm
         math.sin(a * 2.0 * math.pi / 256))
         for a in range(256)]

def noise(x, y, per):
    def surflet(gridX, gridY):
        return polyX * polyY * grad







def fBm(x, y, per, octs):
    val = 0
    for o in range(octs):
    return val

Put that together and you get something like this:

for y in range(size):
    for x in range(size):
im.putdata(data, 128, 128)

Tileable fBm Noise

As you can see, this does indeed tile seamlessly:

fBm Noise, Tiled



Hope this helps!

  • 3
    \$\begingroup\$ im not a python guy, so i ask, how does x*2**o convert to C? is it: x*pow(2,o) or pow(x*2,o) ? \$\endgroup\$ – idev Feb 11 '12 at 14:49
  • 7
    \$\begingroup\$ x*pow(2, o), since exponentiation has higher precedence than multiplication. \$\endgroup\$ – John Calsbeek Feb 11 '12 at 19:05
  • 1
    \$\begingroup\$ could someone convert this to C? i have huge problems understanding this code, as i have never done anything with python. for example what is a value? and im not sure how the functions convert to C... i get straight lines in output only. \$\endgroup\$ – idev Feb 12 '12 at 15:06
  • 1
    \$\begingroup\$ This is definitely the best solution so long as you're fine with the domain of your noise being tied to the shape of your tile. For example, this doesn't allow arbitrary rotations. But if you don't need any such thing, this is the ideal answer. \$\endgroup\$ – John Calsbeek Feb 12 '12 at 22:49
  • 1
    \$\begingroup\$ Note: if you want to generate other size than 128, DO NOT change the numeric values on the line im.putdata(data, 128, 128). (For those unfamiliar with python or PIL: they mean scale and offset, not image size.) \$\endgroup\$ – Antti Kissaniemi Aug 30 '13 at 3:05

Here's one rather clever way that uses 4D Perlin noise.


Copy-pasting code from the article:

for x=0,bufferwidth-1,1 do
    for y=0,bufferheight-1,1 do
        local s=x/bufferwidth
        local t=y/bufferheight
        local dx=x2-x1
        local dy=y2-y1


  • 3
    \$\begingroup\$ This is definitely the right answer. Add dimensions is an old mathematician trick. Olinde Rodrigues docet (Sir W.R. Hamilton docet too but slightly less) \$\endgroup\$ – FxIII Feb 10 '12 at 15:18
  • \$\begingroup\$ @FxIII, do you know how this Noise4D() should be implemented? i would like to try this but i have no clue how this Noise4D() should work. \$\endgroup\$ – idev Feb 10 '12 at 19:44
  • 4
    \$\begingroup\$ You can use any 4D noise function. Simplex noise would be my recommendation. webstaff.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf \$\endgroup\$ – John Calsbeek Feb 10 '12 at 20:20
  • 2
    \$\begingroup\$ thanks john! got it working, sweet! nobody said it, but: the x1,y1,x2,y2 seems to be some sort of scaling, the larger distance, the detailed noise. if this helps anyone. \$\endgroup\$ – idev Feb 10 '12 at 21:02
  • 5
    \$\begingroup\$ Note that this is topologically equivalent to bobobobo's answer: your mapping embeds a 2-torus into an ℝ⁴, which is possible without the metric distortions you invevitably get when embedding it into ℝ³. \$\endgroup\$ – leftaroundabout Feb 11 '12 at 13:21


torus wraps 2 dirs


Color Sky( double x, double y, double z )
  // Calling PerlinNoise3( x,y,z ),
  // for this to tile correctly




tilable sky

And tiled:

showing it tiles

  • 6
    \$\begingroup\$ It kinda works, but it looks like you're getting a bunch of distortion due to the curvature of the torus. \$\endgroup\$ – Nathan Reed Feb 10 '12 at 21:51
  • 1
    \$\begingroup\$ you can really just modulo the position, but I love all the awesome/creative answers to this question. So many different ways to do the same thing. \$\endgroup\$ – user10968 Feb 11 '12 at 8:57
  • \$\begingroup\$ i noticed you actually dont want to use 0-1 values, but 0-0.9999... values! so you would use: x/width, y/height etc. otherwise the seams doesnt match (makes the opposite edges exact same pixels). also it looks like the PerlinNoise3D() function needs clamping for the result value too, or some pixel values overflow. \$\endgroup\$ – idev Feb 11 '12 at 15:52
  • \$\begingroup\$ @Nathan, do you know how to fix the distortion ? \$\endgroup\$ – idev Feb 11 '12 at 15:53
  • 2
    \$\begingroup\$ @idev I believe the way to fix the distortion is to use the 4D method in the top answer of this question. ;) \$\endgroup\$ – Nathan Reed Feb 11 '12 at 16:24





Hope this helps.

  • 3
    \$\begingroup\$ Very nice but too symmetrical! \$\endgroup\$ – bobobobo Feb 10 '12 at 18:18
  • 1
    \$\begingroup\$ @bobobobo That's what I was thinking the other steps would alleviate. So, you could generate a "base" using this method, and then add some more details over the whole thing to make it look like it's not (so) mirrored. \$\endgroup\$ – Richard Marskell - Drackir Feb 10 '12 at 18:29
  • \$\begingroup\$ You start to get some weird patterns when you do this kind of thing. This one in particular looks kind of like a butterfly. Easy solution, though. \$\endgroup\$ – notlesh Feb 10 '12 at 21:04
  • \$\begingroup\$ This was my first approach too, but it has a problem, visible here: dl.dropbox.com/u/6620757/noise_seam.png As you cross a flip boundary you cause a disjoint in the noise function by instantly inverting the slope of the function. Even if you apply a second noise function on top, that may still be visible in the output. \$\endgroup\$ – Jherico Nov 25 '12 at 22:57
  • \$\begingroup\$ Great idea. This can be easily done in a pixel shader using triangle wave function : tex2d(abs(abs(uv.x)%2.0-1.0), abs(abs(uv.y)%2.0-1.0)) \$\endgroup\$ – tigrou May 16 '16 at 12:13

First version of this answer was actually wrong, I've updated it



function InterpolatedNoise_1D(float x)

  integer_X    = int(x)
  fractional_X = x - integer_X

  v1 = SmoothedNoise1(integer_X)
  v2 = SmoothedNoise1(integer_X + 1)

  return Interpolate(v1 , v2 , fractional_X)

end function


integer_X = integer_X % Period



  • \$\begingroup\$ But how do you make noise2 periodic (with a short period such as 1 unit)? I think that's what the question is ultimately asking. Standard Perlin noise is periodic with a period of 256 on each axis but you want a modified noise with a smaller period. \$\endgroup\$ – Nathan Reed Feb 10 '12 at 6:52
  • \$\begingroup\$ @Nathan Reed If you call noise2 as suggested, you will get periodic results, whether the function itself is periodic or not. Because the arguments wrap around every 1 unit. \$\endgroup\$ – Nevermind Feb 10 '12 at 7:01
  • 1
    \$\begingroup\$ But then you get seams at the grid lines, don't you? Since there's no guarantee that noise2(0, 0.999) is anything near noise2(0, 0), unless I've missed something. \$\endgroup\$ – Nathan Reed Feb 10 '12 at 17:30
  • 1
    \$\begingroup\$ @Nathan Reed That's a good point. In fact, I just re-checked my old code and it turns out I was wrong. I'll edit the answer now. \$\endgroup\$ – Nevermind Feb 10 '12 at 18:57
  • \$\begingroup\$ Great! This is actually a good answer now. +1 :) \$\endgroup\$ – Nathan Reed Feb 10 '12 at 19:31





Perlin perlin = new Perlin();
perlin.Frequency = 0.5f;                //height
perlin.Lacunarity = 2f;                 //frequency increase between octaves
perlin.OctaveCount = 5;                 //Number of passes
perlin.Persistence = 0.45f;             //
perlin.Quality = QualityMode.High;
perlin.Seed = 8;

//Create our 2d map

//Get a section
_map.GeneratePlanar(left, right, top, down);









Here's a much much simpler way to do tiled noise:

tiling perlin noise from shadertoy code




#define TILES 2.0

float Hash(in vec2 p, in float scale)
    p = mod(p, scale);

float Noise(in vec2 x, in float scale )
    x *= scale;

    vec2 p = floor(x);
    vec2 f = fract(x);
    return res;

float fBm(in vec2 p)
    float f = 0.4;
    // Change starting scale to any integer value...
    float scale = 14.0;
    float amp = 0.55;
        f += Noise(p, scale) * amp;
        amp *= -.65;
        scale *= 2.0;
    return f;

void main(void)
    vec2 uv = gl_FragCoord.xy / iResolution.xy;

    uv *= TILES;

    // Do the noise cloud (fractal Brownian motion)
    float bri = fBm(uv);

    vec3 col = vec3(bri);

    vec2 pixel = (TILES / iResolution.xy);
    // Flash borders...
        col = vec3(1.0, 1.0, 0.0);
    gl_FragColor = vec4(col,1.0);
  • 1
    \$\begingroup\$ Your image link went dead. I took a best guess & replaced it with a screen shot of the output from the shadertoy code you posted. If that's not correct, please re-upload your intended image directly to the Stack Exchange server. \$\endgroup\$ – Pikalek Aug 22 '18 at 14:26



I was checking this thread in search for an answer to a similar issue, then I got a clean and compact solution from the developer of this python code to generate fractal noise out of perlin/simplex noise. The updated code is provided in this (closed) issue and can be resumed in setting the gradients for the right side of the "generator" equal to those on the left side (and same for top and bottom), such as in

# Gradients
angles = 2*np.pi*np.random.rand(res[0]+1, res[1]+1)
gradients = np.dstack((np.cos(angles), np.sin(angles)))
# Make the noise tileable
gradients[-1,:] = gradients[0,:]
gradients[:,-1] = gradients[:,0]

Seems like an elegant and clean solution, I avoid copying the whole code here (since it's not my own solution), but it's available at the link given above. Hope this can be useful to someone looking to produce a tileable fractal 2d image like this one I needed, free of artifacts or distorsions.

tileable fractal terrain


Your Answer

