I'm not sure if my Perlin Noise generator is functioning properly, the noise it generates looks very different from the images I see online. Mine looks too homogeneous (these are three different images):
Whereas what I usually see is something like:
My code is basically:
/* Get the coord of the top-left gradient of the grid (y, x) falls in */
int j = floor(x);
int i = floor(y);
/* Get the distance (y, x) is from it */
double dx = x-j;
double dy = y-i;
/* Influence of (g)radient(i)(j) (starting at the top-left one) */
double g00 = dot(grad(hashes, hsize, grads, i, j), dy, dx);
double g01 = dot(grad(hashes, hsize, grads, i, j+1), dy, dx-1);
double g10 = dot(grad(hashes, hsize, grads, i+1, j), dy-1, dx);
double g11 = dot(grad(hashes, hsize, grads, i+1, j+1), dy-1, dx-1);
/* Interpolate the influences using the blending function */
/* Linear interpol the top 2 */
double lt = lerp(g00, g01, fade(dx));
/* Linear interpol the bottom 2 */
double lb = lerp(g10, g11, fade(dx));
/* Linear interpol lb lt, completing the bilienear interpol */
return lerp(lt, lb, fade(dy));
Complete code. It's based mainly on this tutorial. I'm using this script to draw the csv file.
I understand the basics, but after reading several "tutorials" that usually contradict each other and the "reference implementation" which is not very readable I have a few doubts. The (x, y)
points being interpolated should be in what interval? As I understand it, it should be [0, GRID_SIZE-1]
(e.g. [0, 255]
if using a pre-computed table with 256 random values). However, my code only results in reasonably good looking images when (x, y)
is mapped to [0, 1]
, and I see some implementations online that map it to [0, 255]
no matter the grid size. I'm also unsure if I'm picking the gradients correctly from the table.
You normalize your pixel coordinates to the whole image. You should normalize it to the size of your simplex grid.
So instead of your code for the inner loop:
double x = j/(double)w;
double y = i/(double)h;
do:
double x = j / gridsize;
double y = i / gridsize;
where the grid size is an additional parameter, for example:
double gridsize = 32.0;
(It should probably be chosen to fit evenly into the image dimensions.)