5

I've been interested (as a hobbyist) in pseudo-random noise generation, specifically the Perlin and Simplex algorithms. The advantage to Simplex is speed (especially at higher dimensions), but Perlin can be tiled relatively easily. I was wondering if anyone was aware of a tiling simplex algorithm? Fixed-dimension is fine, generic is better; pseudocode is fine, c/c++ is better.

fbrereto
  • 35,429
  • 19
  • 126
  • 178
  • 1
    [This question was also answered here](http://gamedev.stackexchange.com/questions/23625/how-do-you-generate-tileable-perlin-noise), though the answers here are also interesting – bobobobo Feb 11 '12 at 04:12
  • 1
    I have wasted several days working on tiling Simplex Noise, only to find out that it is PATENTED (US Patent #6867776)! Total waste of my time. Don't waste yours, use the "Classic Noise" instead. –  May 24 '11 at 07:37
  • And Perlin Noise isn't patented? http://www.wikipatents.com/US-Patent-6867776/standard-for-perlin-noise and just in case if you didn't know, Kenneth Perlin created Simplex noise to replace his old Perlin noise, since it's faster and has less artifacts. – Jón Trausti Arason Jun 22 '11 at 13:03
  • I had the same question in mind some time back. This link may help you a bit. http://www.gamedev.net/community/forums/topic.asp?topic_id=409855 – rayimag Aug 21 '09 at 18:07
  • Thanks for the link; unfortunately the end of the thread concludes that the implementations only have tiling Perlin noise, not Simplex noise. – fbrereto Aug 21 '09 at 18:32

4 Answers4

4

Just tile your noise the same way you would in Perlin only do it after the skew. You can do this by modifying the part that gets the permutaions to do the mod 256 (or & 255, whatever you are using) after (instead of before) you add to offsets to the get the other corners from the base corner. This is the modified bit of code in HLSL:

uint3 iIdx0 = p0SI % 256;
uint3 iIdx1 = (p0SI + pI1) % 256;
uint3 iIdx2 = (p0SI + pI2) % 256;
uint3 iIdx3 = (p0SI + 1.0f) % 256;
uint iGI0 = gPerm[ iIdx0.x + gPerm[ iIdx0.y + gPerm[ iIdx0.z ] ] ] % 12;
uint iGI1 = gPerm[ iIdx1.x + gPerm[ iIdx1.y + gPerm[ iIdx1.z ] ] ] % 12;
uint iGI2 = gPerm[ iIdx2.x + gPerm[ iIdx2.y + gPerm[ iIdx2.z ] ] ] % 12;
uint iGI3 = gPerm[ iIdx3.x + gPerm[ iIdx3.y + gPerm[ iIdx3.z ] ] ] % 12;

p0SI is the corner 0 point and pI2 and PI2 are vectors to corner one and corner 2 calculated in the usual way. Note that in HLSL scalars promote to vectors automatically in mixed operatons so for instance 1.0f is actually (1.0,1.0,1.0). I just figured this tiling stuf out but apprently it works. If you need to shade a large planet or some shit but only have single precision on your card there are a few more steps. Hit me up.

Edit: you know after thinking about it some more I don't think you have to change anything. I think it tiles autmatically at 256 units as implemented.

animuson
  • 53,861
  • 28
  • 137
  • 147
Joe Blow
  • 71
  • 3
3

It would seem this question has been reasonably solved here, with a detailed description of the idea behind the working solution here. A fantastic answer to a long-standing problem!

Community
  • 1
  • 1
fbrereto
  • 35,429
  • 19
  • 126
  • 178
  • Higher-dimensional noise doesn't have the same properties, though. https://computergraphics.stackexchange.com/q/4212/15908 – endolith Mar 10 '21 at 15:38
2

Even if few years passed, this question is still among best results on Google.

In simplex noise, x and y from a straight (ortonormal) grid get skewed to find the simplex the point is in (a triangle in 2D), so with common tiling techniques (%255 or whatever), it DOES tile, but tiles on skewed coordinates, that is it tiles "diagonally", which is quite useless.

A simple solution I've found is to "un-skew" the result, so that original X and Y are first skewed "to the left", then the algorithm will skew them "to the right", and the final result will be re-aligned to a non skewed grid.

If, for example, your simplex implementation is similar to SimplexNoise.java you can find everywhere on the net, it skews the grid using :

var F2 = 0.5*(Math.sqrt(3.0)-1.0);
var s = (xin+yin)*F2; // Hairy factor for 2D
var i = Math.floor(xin+s);
var j = Math.floor(yin+s);

You can simply "pre-skew" it in the opposite direction at the entry point of the method:

var G2 = (3.0-Math.sqrt(3.0))/6.0;
var t = (xin+yin)*G2;
xin-=t;
yin-=t;

Unfortunately, it produces a somehow strange-looking effect (that is, it looks a bit skewed :D ), which is not usually a problem, but depends on what you need that noise for.

Since it was a problem for me, I tried applying this "inverse-skewing" only to a couple of octaves, those that weight more in the final output, and instead used interpolation for "lighter" octaves. This solution gave me satisfactory tiling based on simplex Perlin noise, cause interpolation on all octaves would produce too much attenuation on tile borders, and when more octaves are added without artificial skewing the strage-looking effect gets buried under the additional noise.

Simone Gianni
  • 11,426
  • 40
  • 49
  • This is the best answer I've found to this anywhere. I've just stuck to using perlin noise since tiling it is much easier, but the key is skew transforms. I believe appropriately skewing is possible, but I've not found anyone whose managed to do that yet. – Krupip Aug 31 '18 at 20:59
1

I recently needed tiling simplex noise and came across this question.

For tiling noise using any noise function, you can linearly interpolate additional tile samples:

Ftileable(x, y) = ( 
       F(x, y) * (w - x) * (h - y) + 
       F(x - w, y) * (x) * (h - y) + 
       F(x - w, y - h) * (x) * (y) + 
       F(x, y - h) * (w - x) * (y)
) / (wh)

where F() is your noise function. Note that x, y must be coordinates within an individual tile: x in [0, w), y in [0, h). You could use something like tileX = x - Math.Floor(x / w) * w or fmod().

If performance is critical or for higher dimensions, this may not be the way to go because it requires 2^D lookups for dimension D. It also produced lower values toward the centers of tiles for me.

Taken from: http://webstaff.itn.liu.se/~stegu/TNM022-2005/perlinnoiselinks/perlin-noise-math-faq.html

BenC
  • 11
  • 2
  • That's tiling Perlin noise, however, not Simplex noise. – fbrereto Sep 08 '10 at 16:06
  • The link discusses Perlin noise, but doesn't explicitly state that the method is for it only. I have a working 2D implementation tiling simplex noise, but chose an alternative because the amplitude is decreased toward the tile centers. Gabor noise seems to produce good results and tiles without having to resort to this method (http://graphics.cs.kuleuven.be/publications/LLDD09PNSGC/). – BenC Sep 09 '10 at 21:36