I\'ve recently been trying to implement a Perlin Noise generator in C (based off Ken Perlin\'s website, using the SDL library as a screen output), but the output shows that
It's a problem with the original implementation of Perlin noise.
He has a paper on it here
During the calculation of the gradient at integer coordinates, one or more of the vectors used will be 0, hence the overall gradient will be 0. As a result you get a grid of lines at the integer coordinates.
One way to fix this is to have the coordinate space go from 0 to 1 rather 0 to 512.
Another way is to implement the fix as describer in his paper.
Or finally, don't use the original Perlin Noise, instead swap to Simplex Noise which he also developed, paper here, and explanation here.
I have finally found the problem: the gradient generator.
I was assuming that the random() function would pass its binary value to the grads[] array, covering the whole range of floating point numbers in the way. Unfortunately, that was not the case: its return value was being converted first into a float, then stored in the array. My biggest issue with this was that all generated vectors had positive member values.
This justified the block artifacts: there were lots of "hills" (high values) being generated next to each other, but no "valleys" (low values), and two adjacent hills would eventually clash and generate the lines along the integer values.
After realizing this, I tried to do some pointer juggling and storing the values directly in Uint32 form, but the values in the gradients became wacky (infs, NaNs, 1.0s and 0.0s all the way), so I came back to the original route and negated the numbers in the code itself.
This 7-liner solved the whole problem:
int y=random()&7;
if(y&1)
grads[3*x]*=-1.0f;
if(y&2)
grads[3*x+1]*=-1.0f;
if(y&4)
grads[3*x+2]*=-1.0f;
Just place it before or after the normalizing function and it's done.
Now it looks like Perlin Noise:
And the fractal sum also looks a bit better:
@DiJuMx: I've seen the "Improving Noise" paper before, but hadn't realized how much the gradients would affect the noise appearance. Also, by trying to change the coordinate space from 0~256 to 0~1 resulted in the fractal sum not working anymore, and the resulting image had the same block artifacts.