LYGIA Shader Library

interleavedGradientNoise (lygia/color/dither/interleavedGradientNoise)

Jimenez 2014, "Next Generation Post-Processing Call of Duty" http://advances.realtimerendering.com/s2014/index.html

Dependencies:

Use:

<vec4|vec3|float> interleavedGradientNoise(<vec4|vec3|float> value, <float> time)

Check it on Github



#ifndef DITHER_INTERLEAVEDGRADIENTNOISE_COORD
#define DITHER_INTERLEAVEDGRADIENTNOISE_COORD gl_FragCoord.xy
#endif

#ifdef DITHER_TIME
#define DITHER_INTERLEAVEDGRADIENTNOISE_TIME DITHER_TIME
#endif

#ifndef DITHER_INTERLEAVEDGRADIENTNOISE_PRECISION
#ifdef DITHER_PRECISION
#define DITHER_INTERLEAVEDGRADIENTNOISE_PRECISION DITHER_PRECISION
#else
#define DITHER_INTERLEAVEDGRADIENTNOISE_PRECISION 255
#endif
#endif

#ifndef FNC_DITHER_INTERLEAVEDGRADIENTNOISE
#define FNC_DITHER_INTERLEAVEDGRADIENTNOISE

float ditherInterleavedGradientNoise(vec2 st) {
    #ifdef DITHER_INTERLEAVEDGRADIENTNOISE_TIME
    st += 1337.0*fract(DITHER_INTERLEAVEDGRADIENTNOISE_TIME);
    #endif
    st = floor(st);
    return fract(52.982919 * fract(dot(vec2(0.06711, 0.00584), st))) * 2.0 - 1.0;
}

float ditherInterleavedGradientNoise(const float value, const vec2 st, const int pres) {
    float ditherPattern = ditherInterleavedGradientNoise(st);
    return value + ditherPattern / 255.0;
}

vec3 ditherInterleavedGradientNoise(const vec3 color, const vec2 st, const int pres) {
    #ifdef DITHER_INTERLEAVEDGRADIENTNOISE_CHROMATIC 
    vec3 ditherPattern = vec3(
            ditherInterleavedGradientNoise(st),
            ditherInterleavedGradientNoise(st + 0.1337),
            ditherInterleavedGradientNoise(st + 0.3141));
    #else
    vec3 ditherPattern = vec3(ditherInterleavedGradientNoise(st));
    #endif

    // return color + ditherPattern / 255.0;

    float d = float(pres);
    float h = 0.5 / d;
    // vec3 decimated = decimate(color, d);
    // vec3 diff = (color - decimated) * d;
    // ditherPattern = step(ditherPattern, diff);
    return decimate(color - h + ditherPattern / d, d);
}

// float ditherInterleavedGradientNoise(const float b, const vec2 st) { return b + triangleNoise(st) / float(DITHER_INTERLEAVEDGRADIENTNOISE_PRECISION); }
vec3 ditherInterleavedGradientNoise(const vec3 color, const vec2 xy) {  return ditherInterleavedGradientNoise(color, xy, DITHER_INTERLEAVEDGRADIENTNOISE_PRECISION); }
vec4 ditherInterleavedGradientNoise(const vec4 color, const vec2 xy) {  return vec4(ditherInterleavedGradientNoise(color.rgb, xy, DITHER_INTERLEAVEDGRADIENTNOISE_PRECISION), color.a); }

float ditherInterleavedGradientNoise(const float val, int pres) { return ditherInterleavedGradientNoise(vec3(val),DITHER_INTERLEAVEDGRADIENTNOISE_COORD, pres).r; }
vec3 ditherInterleavedGradientNoise(const vec3 color, int pres) { return ditherInterleavedGradientNoise(color, DITHER_INTERLEAVEDGRADIENTNOISE_COORD, pres); }
vec4 ditherInterleavedGradientNoise(const vec4 color, int pres) { return vec4(ditherInterleavedGradientNoise(color.rgb, DITHER_INTERLEAVEDGRADIENTNOISE_COORD, pres), color.a); }

float ditherInterleavedGradientNoise(const float val) { return ditherInterleavedGradientNoise(vec3(val), DITHER_INTERLEAVEDGRADIENTNOISE_COORD, DITHER_INTERLEAVEDGRADIENTNOISE_PRECISION).r; }
vec3 ditherInterleavedGradientNoise(const vec3 color) { return ditherInterleavedGradientNoise(color, DITHER_INTERLEAVEDGRADIENTNOISE_COORD, DITHER_INTERLEAVEDGRADIENTNOISE_PRECISION); }
vec4 ditherInterleavedGradientNoise(const vec4 color) { return vec4(ditherInterleavedGradientNoise(color.rgb), color.a); }

#endif

Use:

<float4|float3|float> interleavedGradientNoise(<float4|float3|float> value, <float> time)

Check it on Github


#ifdef DITHER_ANIMATED
#define DITHER_INTERLEAVEDGRADIENTNOISE_ANIMATED
#endif

#ifndef FNC_DITHER_INTERLEAVEDGRADIENTNOISE
#define FNC_DITHER_INTERLEAVEDGRADIENTNOISE

float interleavedGradientNoise(const in float2 n) {
    return frac(52.982919 * frac(dot(float2(0.06711, 0.00584), n)));
}

float ditherInterleavedGradientNoise(float b, float2 fragcoord, const in float time) {
    #ifdef DITHER_INTERLEAVEDGRADIENTNOISE_ANIMATED
    fragcoord += 1337.0 * frac(time);
    #endif
    float noise = interleavedGradientNoise(fragcoord);
    // remap from [0..1[ to [-1..1[
    noise = (noise * 2.0) - 1.0;
    return b + noise / 255.0;
}

float3 ditherInterleavedGradientNoise(float3 rgb, float2 fragcoord, const in float time) {
    #ifdef DITHER_INTERLEAVEDGRADIENTNOISE_ANIMATED
    fragcoord += 1337.0 * frac(time);
    #endif
    float noise = interleavedGradientNoise(fragcoord);
    // remap from [0..1[ to [-1..1[
    noise = (noise * 2.0) - 1.0;
    return rgb.rgb + noise / 255.0;
}

float4 ditherInterleavedGradientNoise(float4 rgba, float2 fragcoord, const in float time) {
    return float4(ditherInterleavedGradientNoise(rgba.rgb, fragcoord, time), rgba.a);
}

#endif

Dependencies:

Use:

<float4|float3|float> interleavedGradientNoise(<float4|float3|float> value, <float> time)

Check it on Github




#ifdef DITHER_TIME
#define DITHER_INTERLEAVEDGRADIENTNOISE_TIME DITHER_TIME
#endif

#ifndef DITHER_INTERLEAVEDGRADIENTNOISE_PRECISION
#ifdef DITHER_PRECISION
#define DITHER_INTERLEAVEDGRADIENTNOISE_PRECISION DITHER_PRECISION
#else
#define DITHER_INTERLEAVEDGRADIENTNOISE_PRECISION 255
#endif
#endif

#ifndef FNC_DITHER_INTERLEAVEDGRADIENTNOISE
#define FNC_DITHER_INTERLEAVEDGRADIENTNOISE

float ditherInterleavedGradientNoise(float2 st) {
    #ifdef DITHER_INTERLEAVEDGRADIENTNOISE_TIME
    st += 1337.0*fract(DITHER_INTERLEAVEDGRADIENTNOISE_TIME);
    #endif
    st = floor(st);
    return fract(52.982919 * fract(dot(float2(0.06711, 0.00584), st))) * 2.0 - 1.0;
}

float ditherInterleavedGradientNoise(const float value, const float2 st, const int pres) {
    float ditherPattern = ditherInterleavedGradientNoise(st);
    return value + ditherPattern / 255.0;
}

float3 ditherInterleavedGradientNoise(const float3 color, const float2 st, const int pres) {
    #ifdef DITHER_INTERLEAVEDGRADIENTNOISE_CHROMATIC 
    float3 ditherPattern = float3(
            ditherInterleavedGradientNoise(st),
            ditherInterleavedGradientNoise(st + 0.1337),
            ditherInterleavedGradientNoise(st + 0.3141));
    #else
    float3 ditherPattern = float3(ditherInterleavedGradientNoise(st));
    #endif

    // return color + ditherPattern / 255.0;

    float d = float(pres);
    float h = 0.5 / d;
    // float3 decimated = decimate(color, d);
    // float3 diff = (color - decimated) * d;
    // ditherPattern = step(ditherPattern, diff);
    return decimate(color - h + ditherPattern / d, d);
}

//float ditherInterleavedGradientNoise(const float b, const float2 st) { return b + triangleNoise(st) / float(DITHER_INTERLEAVEDGRADIENTNOISE_PRECISION); }
float3 ditherInterleavedGradientNoise(const float3 color, const float2 xy) {  return ditherInterleavedGradientNoise(color, xy, DITHER_INTERLEAVEDGRADIENTNOISE_PRECISION); }
float4 ditherInterleavedGradientNoise(const float4 color, const float2 xy) {  return float4(ditherInterleavedGradientNoise(color.rgb, xy, DITHER_INTERLEAVEDGRADIENTNOISE_PRECISION), color.a); }

#endif

Examples

Licenses

LYGIA is dual-licensed under the Prosperity License and the Patron License for sponsors and contributors.

Sponsors and contributors are automatically added to the Patron License and they can ignore the any non-commercial rule of the Prosperity Licensed software (please take a look to the exception).

It's also possible to get a permanent comercial license hook to a single and specific version of LYGIA.

Get the latest news and releases

Sign up for the news letter bellow, joing the LYGIA's channel on Discord or follow the Github repository