<p>The noise is defined using a rectangular regular lattice. This lattice contains cells in which the noise is evaluated using the four corner points of this cell. At every point of the lattice a pseudo-random gradient is defined. The hash function is simply a compact way of defining a pseudo-random function that given coordinates of a point of the lattice <span class="math-container">$(i,j)$</span> returns a pseudo-random gradient. In this way the gradient vector is the same for all cells which are adjacent to lattice point <span class="math-container">$(i, j)$</span>.</p>
<p>The reason it says the hash function should be replaced by something better is because it is a very simple hash function which when evaluated might not be too random at all and periodicities might be observed in the generated noise field.</p>

CC BY-SA 4.0
2021-09-02T10:09:21.783Z
Thanks! I was able to figure it yesterday, nice seeing that I had come to the right conclusion.
Frank Weslien
CC BY-SA 4.0
2021-09-01T09:26:19.070Z
2021-09-01T09:26:19.070Z
Reynolds
<p>When attempting to compute the gradient noise derivatives I've seen the use of a function named &quot;hash&quot; and I don't understand its purpose (nor why they have commented that it should be replaced by something better): <a href="https://www.shadertoy.com/view/XdXBRH" rel="nofollow noreferrer">link</a></p>
<p>Code:</p>
<pre><code>vec2 hash( in vec2 x )  // replace this by something better
{
    const vec2 k = vec2( 0.3183099, 0.3678794 );
    x = x*k + k.yx;
    return -1.0 + 2.0*fract( 16.0 * k*fract( x.x*x.y*(x.x+x.y)) );
}


// return gradient noise (in x) and its derivatives (in yz)
vec3 noised( in vec2 p )
{
    vec2 i = floor( p );
    vec2 f = fract( p );

#if 1
    // quintic interpolation
    vec2 u = f*f*f*(f*(f*6.0-15.0)+10.0);
    vec2 du = 30.0*f*f*(f*(f-2.0)+1.0);
#else
    // cubic interpolation
    vec2 u = f*f*(3.0-2.0*f);
    vec2 du = 6.0*f*(1.0-f);
#endif    
    
    vec2 ga = hash( i + vec2(0.0,0.0) );
    vec2 gb = hash( i + vec2(1.0,0.0) );
    vec2 gc = hash( i + vec2(0.0,1.0) );
    vec2 gd = hash( i + vec2(1.0,1.0) );
    
float va = dot( ga, f - vec2(0.0,0.0) );
float vb = dot( gb, f - vec2(1.0,0.0) );
float vc = dot( gc, f - vec2(0.0,1.0) );
float vd = dot( gd, f - vec2(1.0,1.0) );

return vec3( va + u.x*(vb-va) + u.y*(vc-va) + u.x*u.y*(va-vb-vc+vd),   // value
             ga + u.x*(gb-ga) + u.y*(gc-ga) + u.x*u.y*(ga-gb-gc+gd) +  // derivatives
             du * (u.yx*(va-vb-vc+vd) + vec2(vb,vc) - va));
}

// -----------------------------------------------

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 p = (2.0*fragCoord-iResolution.xy)/iResolution.y;
    
    vec3 n = noised( 8.0*p + iTime*4.0 );

    vec3 col = 0.5 + 0.5*((p.x&gt;0.0) ? n.yzx : n.xxx);
    
    fragColor = vec4( col, 1.0 );
}
</code></pre>

<c++>
Understanding how gradient noise generation works
Frank Weslien
# Understanding how gradient noise generation works

(Asked by: username_0 on 2021-08-31)

When attempting to compute the gradient noise derivatives I've seen the use of a function named "hash" and I don't understand its purpose (nor why they have commented that it should be replaced by something better): [link](https://www.shadertoy.com/view/XdXBRH)

Code:

```
vec2 hash( in vec2 x )  // replace this by something better
{
    const vec2 k = vec2( 0.3183099, 0.3678794 );
    x = x*k + k.yx;
    return -1.0 + 2.0*fract( 16.0 * k*fract( x.x*x.y*(x.x+x.y)) );
}

// return gradient noise (in x) and its derivatives (in yz)
vec3 noised( in vec2 p )
{
    vec2 i = floor( p );
    vec2 f = fract( p );

#if 1
    // quintic interpolation
    vec2 u = f*f*f*(f*(f*6.0-15.0)+10.0);
    vec2 du = 30.0*f*f*(f*(f-2.0)+1.0);
#else
    // cubic interpolation
    vec2 u = f*f*(3.0-2.0*f);
    vec2 du = 6.0*f*(1.0-f);
#endif    
    
    vec2 ga = hash( i + vec2(0.0,0.0) );
    vec2 gb = hash( i + vec2(1.0,0.0) );
    vec2 gc = hash( i + vec2(0.0,1.0) );
    vec2 gd = hash( i + vec2(1.0,1.0) );
    
float va = dot( ga, f - vec2(0.0,0.0) );
float vb = dot( gb, f - vec2(1.0,0.0) );
float vc = dot( gc, f - vec2(0.0,1.0) );
float vd = dot( gd, f - vec2(1.0,1.0) );

return vec3( va + u.x*(vb-va) + u.y*(vc-va) + u.x*u.y*(va-vb-vc+vd),   // value
             ga + u.x*(gb-ga) + u.y*(gc-ga) + u.x*u.y*(ga-gb-gc+gd) +  // derivatives
             du * (u.yx*(va-vb-vc+vd) + vec2(vb,vc) - va));
}

// -----------------------------------------------

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 p = (2.0*fragCoord-iResolution.xy)/iResolution.y;
    
    vec3 n = noised( 8.0*p + iTime*4.0 );

    vec3 col = 0.5 + 0.5*((p.x>0.0) ? n.yzx : n.xxx);
    
    fragColor = vec4( col, 1.0 );
}

```

**Tags:** c++


---

## 1 answers

### Answer by username_1 on 2021-09-01. Score: 1

The noise is defined using a rectangular regular lattice. This lattice contains cells in which the noise is evaluated using the four corner points of this cell. At every point of the lattice a pseudo-random gradient is defined. The hash function is simply a compact way of defining a pseudo-random function that given coordinates of a point of the lattice $(i,j)$ returns a pseudo-random gradient. In this way the gradient vector is the same for all cells which are adjacent to lattice point $(i, j)$.

The reason it says the hash function should be replaced by something better is because it is a very simple hash function which when evaluated might not be too random at all and periodicities might be observed in the generated noise field.

> **Comments:**
> **username_0**: Thanks! I was able to figure it yesterday, nice seeing that I had come to the right conclusion.  

---

