Why does my Perlin Noise look "blocky"? I tried to implement Perlin Noise by myself using just the theory (following flafla2.github.io/2014/08/09/perlinnoise.html). Unfortunately I was unable to achieve the look of the "original" Perlin Noise.

What's the reason the code below renders a blocky version of Perlin Noise?

What should I improve/change in the code so that it renders Perlin Noise without the artifacts?

I suspect there might be problem either in the way I interpolate or in the grads vector. The grads vector contains dot products of (random vector for lattice point) and (the size vector) – for all 4 nearby lattice points. (The random and size vectors are described in the very first link.)

GLSL Sandbox: http://glslsandbox.com/e#32663.0



float fade(float t) { return t * t * t * (t * (t * 6. - 15.) + 10.); }
vec2 smooth(vec2 x) { return vec2(fade(x.x), fade(x.y)); }

vec2 hash(vec2 co) {
    return fract (vec2(.5654654, -.65465) * dot (vec2(.654, 57.4), co));
}

float perlinNoise(vec2 uv) {
    vec2 PT  = floor(uv);
    vec2 pt  = fract(uv);
    vec2 mmpt= smooth(pt);

    vec4 grads = vec4(
        dot(hash(PT + vec2(.0, 1.)), pt-vec2(.0, 1.)),   dot(hash(PT + vec2(1., 1.)), pt-vec2(1., 1.)),
        dot(hash(PT + vec2(.0, .0)), pt-vec2(.0, .0)),   dot(hash(PT + vec2(1., .0)), pt-vec2(1., 0.))
    );

    return 5.*mix (mix (grads.z, grads.w, mmpt.x), mix (grads.x, grads.y, mmpt.x), mmpt.y);
}

float fbm(vec2 uv) {
    float finalNoise = 0.;
    finalNoise += .50000*perlinNoise(2.*uv);
    finalNoise += .25000*perlinNoise(4.*uv);
    finalNoise += .12500*perlinNoise(8.*uv);
    finalNoise += .06250*perlinNoise(16.*uv);
    finalNoise += .03125*perlinNoise(32.*uv);

    return finalNoise;
}

void main() {
    vec2 position = gl_FragCoord.xy / resolution.y;
    gl_FragColor = vec4( vec3( fbm(3.*position) ), 1.0 );
}
The interpolation looks fine. The main problem here is that the hash function you're using isn't very good. If I look at just one octave, and visualize the hash result by outputting hash(PT).x, I get something like this:



This is supposed to be completely random per grid square, but you can see that it has a lot of diagonal line patterns in it (it almost looks like a checkerboard), so it's not a very random hash, and those patterns will show up in the noise produced by it.

The other problem is that your hash only returns gradient vectors in [0, 1], while they should be in [&minus;1, 1] to get gradients in all directions. That part's easy to fix by remapping.

To fix those problems, I switched the code to use this hash function (which I learned from Mikkel Gjoel, and is probably due to a paper by W.J.J. Rey):

vec2 hash(vec2 co) {
    float m = dot(co, vec2(12.9898, 78.233));
    return fract(vec2(sin(m),cos(m))* 43758.5453) * 2. - 1.;
}


Note that due to the trig functions it's going to be a bit more expensive than your version. However, it considerably improves the appearance of the resulting noise: