LYGIA Shader Library

vlachos (lygia/color/dither/vlachos)

Vlachos 2016, "Advanced VR Rendering" http://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf

Dependencies:

Use:

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

Check it on Github



#ifndef HIGHP
#if defined(TARGET_MOBILE) && defined(GL_ES)
#define HIGHP highp
#else
#define HIGHP
#endif
#endif

#ifndef DITHER_VLACHOS_COORD
#define DITHER_VLACHOS_COORD gl_FragCoord.xy
#endif

#ifdef DITHER_TIME
#define DITHER_VLACHOS_TIME DITHER_TIME
#endif

#ifndef DITHER_VLACHOS_PRECISION
#ifdef DITHER_PRECISION
#define DITHER_VLACHOS_PRECISION DITHER_PRECISION
#else
#define DITHER_VLACHOS_PRECISION 256
#endif
#endif

#ifndef FNC_DITHER_VLACHOS
#define FNC_DITHER_VLACHOS

float ditherVlachos(float b, vec2 st) {
    #ifdef DITHER_VLACHOS_TIME
    st += 1337.0*fract(DITHER_VLACHOS_TIME);
    #endif
    HIGHP float noise = dot(vec2(171.0, 231.0), st);
    noise = fract(noise / 71.0);
    noise = (noise * 2.0) - 1.0;
    return b + (noise / 255.0);
}

vec3 ditherVlachos(vec2 st) {
    #ifdef DITHER_VLACHOS_TIME
    st += 1337.0*fract(DITHER_VLACHOS_TIME);
    #endif
    HIGHP vec3 noise = vec3(dot(vec2(171.0, 231.0), st));
    noise = fract(noise / vec3(103.0, 71.0, 97.0));
    return noise;
}

vec3 ditherVlachos(const in vec3 color, const in vec2 st, const int pres) {
    // return color + ditherVlachos(st) / 255.0;

    float d = float(pres);
    vec3 ditherPattern = ditherVlachos(st);
    return decimate(color + ditherPattern / d, d);
}
vec3 ditherVlachos(const in vec3 color, const in vec2 xy) {
    return ditherVlachos(color, xy, DITHER_VLACHOS_PRECISION);
}

vec4 ditherVlachos(vec4 color, vec2 st) { return vec4(ditherVlachos(color.rgb, st), color.a);}

float ditherVlachos(float val) { return ditherVlachos(val, DITHER_VLACHOS_COORD);}
vec3 ditherVlachos(vec3 color) { return ditherVlachos(color, DITHER_VLACHOS_COORD);}
vec4 ditherVlachos(vec4 color) { return vec4(ditherVlachos(color.rgb), color.a);}

#endif

Use:

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

Check it on Github


#ifdef DITHER_ANIMATED
#define DITHER_VLACHOS_ANIMATED
#endif

#ifndef FNC_DITHER_VLACHOS
#define FNC_DITHER_VLACHOS

float ditherVlachos(float b, float2 fragcoord, const in float time) {
    #ifdef DITHER_VLACHOS_ANIMATED
    fragcoord += 1337.0*frac(time);
    #endif
    float noise = dot(float2(171.0, 231.0), fragcoord);
    noise = frac(noise / 71.0);
    // remap from [0..1[ to [-1..1[
    noise = (noise * 2.0) - 1.0;
    return b + (noise / 255.0);
}

float3 ditherVlachos(float3 rgb, float2 fragcoord, const in float time) {
    #ifdef DITHER_VLACHOS_ANIMATED
    fragcoord += 1337.0 * frac(time);
    #endif
    float n = dot(float2(171.0, 231.0), fragcoord);
    float3 noise = float3(n, n, n);
    noise = frac(noise / float3(103.0, 71.0, 97.0));
    return rgb.rgb + (noise / 255.0);
}

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

#endif

Dependencies:

Use:

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

Check it on Github



#ifndef HIGHP
#if defined(TARGET_MOBILE) && defined(GL_ES)
#define HIGHP highp
#else
#define HIGHP
#endif
#endif


#ifdef DITHER_TIME
#define DITHER_VLACHOS_TIME DITHER_TIME
#endif

#ifndef DITHER_VLACHOS_PRECISION
#ifdef DITHER_PRECISION
#define DITHER_VLACHOS_PRECISION DITHER_PRECISION
#else
#define DITHER_VLACHOS_PRECISION 256
#endif
#endif

#ifndef FNC_DITHER_VLACHOS
#define FNC_DITHER_VLACHOS

float ditherVlachos(float b, float2 st) {
    #ifdef DITHER_VLACHOS_TIME
    st += 1337.0*fract(DITHER_VLACHOS_TIME);
    #endif
    HIGHP float noise = dot(float2(171.0, 231.0), st);
    noise = fract(noise / 71.0);
    noise = (noise * 2.0) - 1.0;
    return b + (noise / 255.0);
}

float3 ditherVlachos(float2 st) {
    #ifdef DITHER_VLACHOS_TIME
    st += 1337.0*fract(DITHER_VLACHOS_TIME);
    #endif
    HIGHP float3 noise = float3(dot(float2(171.0, 231.0), st));
    noise = fract(noise / float3(103.0, 71.0, 97.0));
    return noise;
}

float3 ditherVlachos(const float3 color, const float2 st, const int pres) {
    // return color + ditherVlachos(st) / 255.0;

    float d = float(pres);
    float3 ditherPattern = ditherVlachos(st);
    return decimate(color + ditherPattern / d, d);
}
float3 ditherVlachos(const float3 color, const float2 xy) {
    return ditherVlachos(color, xy, DITHER_VLACHOS_PRECISION);
}

float4 ditherVlachos(float4 color, float2 st) { return float4(ditherVlachos(color.rgb, st), color.a);}

#endif

Dependencies:

Use:

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

Check it on Github



fn ditherVlachos1(ist: vec2f) -> vec3f {
    var st = ist;
    st += 1337.0 * fract(uniforms.frameIdx);
    var noise = vec3(dot(vec2(171.0, 231.0), st));
    noise = fract(noise / vec3(103.0, 71.0, 97.0));
    return noise;
}

fn ditherVlachos3(color: vec3f, st: vec2f, d: vec3f) -> vec3f {
    let ditherPattern = ditherVlachos1(st);
    return decimate3(color + ditherPattern / d, d);
}

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