LYGIA Shader Library

bayer (lygia/color/dither/bayer)

Dither using a 8x8 Bayer matrix

Dependencies:

Use:

<vec4|vec3|float> ditherBayer(<vec4|vec3|float> value, <vec2> st, <float> time)
<vec4|vec3|float> ditherBayer(<vec4|vec3|float> value, <vec2> st)
<float> ditherBayer(<vec2> xy)

Check it on Github



#ifndef DITHER_BAKER_COORD
#define DITHER_BAKER_COORD gl_FragCoord.xy
#endif

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

#ifndef FNC_DITHER_BAYER
#define FNC_DITHER_BAYER

#if defined(PLATFORM_WEBGL)
float ditherBayer(const in vec2 xy) {
    float x = mod(xy.x, 8.0);
    float y = mod(xy.y, 8.0);
    return  mix(mix(mix(mix(mix(mix(0.0,32.0,step(1.0,y)),mix(8.0,40.0,step(3.0,y)),step(2.0,y)),mix(mix(2.0,34.0,step(5.0,y)),mix(10.0,42.0,step(7.0,y)),step(6.0,y)),step(4.0,y)),mix(mix(mix(48.0,16.0,step(1.0,y)),mix(56.0,24.0,step(3.0,y)),step(2.0,y)),mix(mix(50.0,18.0,step(5.0,y)),mix(58.0,26.0,step(7.0,y)),step(6.0,y)),step(4.0,y)),step(1.0,x)),mix(mix(mix(mix(12.0,44.0,step(1.0,y)),mix(4.0,36.0,step(3.0,y)),step(2.0,y)),mix(mix(14.0,46.0,step(5.0,y)),mix(6.0,38.0,step(7.0,y)),step(6.0,y)),step(4.0,y)),mix(mix(mix(60.0,28.0,step(1.0,y)),mix(52.0,20.0,step(3.0,y)),step(2.0,y)),mix(mix(62.0,30.0,step(5.0,y)),mix(54.0,22.0,step(7.0,y)),step(6.0,y)),step(4.0,y)),step(3.0,x)),step(2.0,x)),mix(mix(mix(mix(mix(3.0,35.0,step(1.0,y)),mix(11.0,43.0,step(3.0,y)),step(2.0,y)),mix(mix(1.0,33.0,step(5.0,y)),mix(9.0,41.0,step(7.0,y)),step(6.0,y)),step(4.0,y)),mix(mix(mix(51.0,19.0,step(1.0,y)),mix(59.0,27.0,step(3.0,y)),step(2.0,y)),mix(mix(49.0,17.0,step(5.0,y)),mix(57.0,25.0,step(7.0,y)),step(6.0,y)),step(4.0,y)),step(5.0,x)),mix(mix(mix(mix(15.0,47.0,step(1.0,y)),mix(7.0,39.0,step(3.0,y)),step(2.0,y)),mix(mix(13.0,45.0,step(5.0,y)),mix(5.0,37.0,step(7.0,y)),step(6.0,y)),step(4.0,y)),mix(mix(mix(63.0,31.0,step(1.0,y)),mix(55.0,23.0,step(3.0,y)),step(2.0,y)),mix(mix(61.0,29.0,step(5.0,y)),mix(53.0,21.0,step(7.0,y)),step(6.0,y)),step(4.0,y)),step(7.0,x)),step(6.0,x)),step(4.0,x)) / (64.0);
}

#else

float ditherBayer(const in vec2 xy) {
    float kern[64];
    kern[ 0] = 0.000; kern[ 1] = 0.500; kern[ 2] = 0.124; kern[ 3] = 0.624; kern[ 4] = 0.028; kern[ 5] = 0.532; kern[ 6] = 0.156; kern[ 7] = 0.656; 
    kern[ 8] = 0.752; kern[ 9] = 0.248; kern[10] = 0.876; kern[11] = 0.376; kern[12] = 0.784; kern[13] = 0.280; kern[14] = 0.908; kern[15] = 0.404; 
    kern[16] = 0.188; kern[17] = 0.688; kern[18] = 0.060; kern[19] = 0.564; kern[20] = 0.216; kern[21] = 0.720; kern[22] = 0.092; kern[23] = 0.596; 
    kern[24] = 0.940; kern[25] = 0.436; kern[26] = 0.812; kern[27] = 0.312; kern[28] = 0.972; kern[29] = 0.468; kern[30] = 0.844; kern[31] = 0.344; 
    kern[32] = 0.044; kern[33] = 0.548; kern[34] = 0.172; kern[35] = 0.672; kern[36] = 0.012; kern[37] = 0.516; kern[38] = 0.140; kern[39] = 0.640; 
    kern[40] = 0.800; kern[41] = 0.296; kern[42] = 0.924; kern[43] = 0.420; kern[44] = 0.768; kern[45] = 0.264; kern[46] = 0.892; kern[47] = 0.392; 
    kern[48] = 0.232; kern[49] = 0.736; kern[50] = 0.108; kern[51] = 0.608; kern[52] = 0.200; kern[53] = 0.704; kern[54] = 0.076; kern[55] = 0.580; 
    kern[56] = 0.988; kern[57] = 0.484; kern[58] = 0.860; kern[59] = 0.360; kern[60] = 0.956; kern[61] = 0.452; kern[62] = 0.828; kern[63] = 0.328;
    int index = int(mod(xy.x, 8.0)) + (int(mod(xy.y, 8.0)) * 8);
    #if defined(PLATFORM_WEBGL)
    for (int i = 0; i < 64; i++) if (i == index) return kern[i];
    #else
    return kern[index];
    #endif
}

#endif

vec3 ditherBayer(vec3 color, const in vec2 xy, const int pres) {
    float d = float(pres);
    vec3 decimated = decimate(color, d);
    vec3 diff = (color - decimated) * d;
    vec3 ditherPattern = vec3(ditherBayer(xy));
    return decimate(color + (step(ditherPattern, diff) / d), d);
}

float ditherBayer(const in float val, const in vec2 xy) { return ditherBayer(vec3(val), xy, DITHER_BAYER_PRECISION).r; }
vec3 ditherBayer(const in vec3 color, const in vec2 xy) {  return ditherBayer(color, xy, DITHER_BAYER_PRECISION); }
vec4 ditherBayer(const in vec4 color, const in vec2 xy) {  return vec4(ditherBayer(color.rgb, xy, DITHER_BAYER_PRECISION), color.a); }

float ditherBayer(const in float val, int pres) { return ditherBayer(vec3(val),DITHER_BAKER_COORD, pres).r; }
vec3 ditherBayer(const in vec3 color, int pres) { return ditherBayer(color, DITHER_BAKER_COORD, pres); }
vec4 ditherBayer(const in vec4 color, int pres) { return vec4(ditherBayer(color.rgb, DITHER_BAKER_COORD, pres), color.a); }

float ditherBayer(const in float val) { return ditherBayer(vec3(val), DITHER_BAKER_COORD, DITHER_BAYER_PRECISION).r; }
vec3 ditherBayer(const in vec3 color) { return ditherBayer(color, DITHER_BAKER_COORD, DITHER_BAYER_PRECISION); }
vec4 ditherBayer(const in vec4 color) { return vec4(ditherBayer(color.rgb), color.a); }
#endif

Dependencies:

Use:

<float4|float3|float> ditherBayer(<float4|float3|float> value, <float2> st, <float> time)
<float4|float3|float> ditherBayer(<float4|float3|float> value, <float2> st)
<float> ditherBayer(<float2> xy)

Check it on Github




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

#ifndef FNC_DITHER_BAYER
#define FNC_DITHER_BAYER

float ditherBayer(const float2 xy) {
    float x = mod(xy.x, 8.0);
    float y = mod(xy.y, 8.0);
    return  mix(mix(mix(mix(mix(mix(0.0,32.0,step(1.0,y)),mix(8.0,40.0,step(3.0,y)),step(2.0,y)),mix(mix(2.0,34.0,step(5.0,y)),mix(10.0,42.0,step(7.0,y)),step(6.0,y)),step(4.0,y)),mix(mix(mix(48.0,16.0,step(1.0,y)),mix(56.0,24.0,step(3.0,y)),step(2.0,y)),mix(mix(50.0,18.0,step(5.0,y)),mix(58.0,26.0,step(7.0,y)),step(6.0,y)),step(4.0,y)),step(1.0,x)),mix(mix(mix(mix(12.0,44.0,step(1.0,y)),mix(4.0,36.0,step(3.0,y)),step(2.0,y)),mix(mix(14.0,46.0,step(5.0,y)),mix(6.0,38.0,step(7.0,y)),step(6.0,y)),step(4.0,y)),mix(mix(mix(60.0,28.0,step(1.0,y)),mix(52.0,20.0,step(3.0,y)),step(2.0,y)),mix(mix(62.0,30.0,step(5.0,y)),mix(54.0,22.0,step(7.0,y)),step(6.0,y)),step(4.0,y)),step(3.0,x)),step(2.0,x)),mix(mix(mix(mix(mix(3.0,35.0,step(1.0,y)),mix(11.0,43.0,step(3.0,y)),step(2.0,y)),mix(mix(1.0,33.0,step(5.0,y)),mix(9.0,41.0,step(7.0,y)),step(6.0,y)),step(4.0,y)),mix(mix(mix(51.0,19.0,step(1.0,y)),mix(59.0,27.0,step(3.0,y)),step(2.0,y)),mix(mix(49.0,17.0,step(5.0,y)),mix(57.0,25.0,step(7.0,y)),step(6.0,y)),step(4.0,y)),step(5.0,x)),mix(mix(mix(mix(15.0,47.0,step(1.0,y)),mix(7.0,39.0,step(3.0,y)),step(2.0,y)),mix(mix(13.0,45.0,step(5.0,y)),mix(5.0,37.0,step(7.0,y)),step(6.0,y)),step(4.0,y)),mix(mix(mix(63.0,31.0,step(1.0,y)),mix(55.0,23.0,step(3.0,y)),step(2.0,y)),mix(mix(61.0,29.0,step(5.0,y)),mix(53.0,21.0,step(7.0,y)),step(6.0,y)),step(4.0,y)),step(7.0,x)),step(6.0,x)),step(4.0,x)) / (64.0);
}

float3 ditherBayer(float3 color, const float2 xy, const int pres) {
    float d = float(pres);
    float3 decimated = decimate(color, d);
    float3 diff = (color - decimated) * d;
    float3 ditherPattern = float3(ditherBayer(xy));
    return decimate(color + (step(ditherPattern, diff) / d), d);
}

float ditherBayer(const float val, const float2 xy) { return ditherBayer(float3(val), xy, DITHER_BAYER_PRECISION).r; }
float3 ditherBayer(const float3 color, const float2 xy) {  return ditherBayer(color, xy, DITHER_BAYER_PRECISION); }
float4 ditherBayer(const float4 color, const float2 xy) {  return float4(ditherBayer(color.rgb, xy, DITHER_BAYER_PRECISION), color.a); }
#endif

Dependencies:

Use:

<vec4|vec3|float> ditherBayer(<vec4|vec3|float> value, <vec2> st, <float> time)
<vec4|vec3|float> ditherBayer(<vec4|vec3|float> value, <vec2> st)
<float> ditherBayer(<vec2> xy)

Check it on Github



fn mod_fract(a: vec2f, b: f32) -> vec2f { return modf(a / b).fract * b; }

const indexMatrix4x4 = array<f32, 16>(0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5);

fn indexValue4(fragCoord: vec2<f32>) -> f32 {
    let p = vec2<i32>(mod_fract(fragCoord, 4));
    return indexMatrix4x4[(p.x + p.y * 4)] / 16.0;
}

const indexMatrix8x8 =
    array<f32, 64>(0, 32, 8, 40, 2, 34, 10, 42, 48, 16, 56, 24, 50, 18, 58, 26, 12, 44, 4, 36, 14, 46, 6, 38, 60, 28,
    52, 20, 62, 30, 54, 22, 3, 35, 11, 43, 1, 33, 9, 41, 51, 19, 59, 27, 49, 17, 57, 25, 15, 47, 7, 39,
    13, 45, 5, 37, 63, 31, 55, 23, 61, 29, 53, 21);

fn indexValue8(fragCoord: vec2<f32>) -> f32 {
    let p = vec2<i32>(mod_fract(fragCoord, 8));
    return indexMatrix8x8[(p.x + p.y * 8)] / 64.0;
}

fn ditherBayer1(ist: vec2f) -> f32 { return indexValue4(ist); }

fn ditherBayer3(color: vec3f, xy: vec2f, d: vec3f) -> vec3f {
    let decimated = decimate3(color, d);
    let diff = (color - decimated) * d;
    let ditherPattern = vec3(ditherBayer1(xy));
    return decimate3(color + (step(ditherPattern, diff) / 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