Tiling Simplex Noise?

那年仲夏 提交于 2019-12-06 05:28:46

问题


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.


回答1:


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.




回答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.




回答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!




回答4:


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



来源:https://stackoverflow.com/questions/1313259/tiling-simplex-noise

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!