2
\$\begingroup\$

I'm looking for a simple (but especially fast) coherent noise function to use it in a shader written in GLSL.

I don't need it to be excessively smooth or good looking, I just need that it has the following properties:

  1. Passing in the same input value will always return the same output value.
  2. A small change in the input value will produce a small change in the output value.
  3. A large change in the input value will produce a random change in the output value.

I really need it to be fast, as it will be called once for each pixel by the GPU (to have an idea of how fast it should be, I tried Perlin Noise and it crashed my application).

What method should I use? I'd also like if the same pattern didn't repeat over time.

\$\endgroup\$
2
\$\begingroup\$

The best you can do is using a texture to get the noise from, note that this is not the same as sampling a noise texture, you are just getting the random values from the texture so you can animate it as a normal noise function. This makes it really fast. If you input the same parameters you will return the same output, and the change in the input value goes according to the change in the output value.

// Courtesy of Iñigo Quilez.
float noise( in vec3 x )
{

    vec3 p = floor(x);
    vec3 f = fract(x);
    f = f*f*(3.0-2.0*f);

    vec2 uv = (p.xy+vec2(37.0,17.0)*p.z) + f.xy;
    vec2 rg = textureLod( iChannel0, (uv+ 0.5)/256.0, 0.0 ).yx;
    return mix( rg.x, rg.y, f.z );

}

This one is also very fast and actually some smartphones may be better off with no texture calls (faster? I am not sure. You'll have to test)

// Pseudo random number generator. 
float hash( vec2 a )
{

    return fract( sin( a.x * 3433.8 + a.y * 3843.98 ) * 45933.8 );

}

// Value noise courtesy of BigWingz 
// check his youtube channel he has
// a video of this one.
// Succint version by FabriceNeyret
float noise( vec2 U )
{
    vec2 id = floor( U );
          U = fract( U );
    U *= U * ( 3. - 2. * U );  

    vec2 A = vec2( hash(id)            , hash(id + vec2(0,1)) ),  
         B = vec2( hash(id + vec2(1,0)), hash(id + vec2(1,1)) ),  
         C = mix( A, B, U.x);

    return mix( C.x, C.y, U.y );
}

The algorithm is pretty simple, you create tiles with your UV's and you assign a random colour to each of the tiles, then you interpolate between them.

Here is a link for you to check Iñigo Quilez but if you are asking for something glsl related you probably know who this guy is.

If you go for the texture based approach you need this texture to get the noise function to work:

NoiseTextureFromShadertoy

Remember to not VFlip it and to have it as GL_REPEAT with MipMap filters.

WebGL Noise2D Demo, comment the VALUENOISE define to see the texture noise.

And a post that I wrote that may be related.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.