Gradient dithering?

This has been on my list to fix for ages.  I've got this far (see little shader below) which does a lovely smooth job, try in in the 'OpenGL 2D' JuceDemo code editor.  


void main()
{
     vec4 colour1 = vec4 (0.2, 0.2, 0.2, 1.0); 
     vec4 colour2 = vec4 (0.05, 0.05, 0.05, 1.0);
     float alpha = float(pixelPos.x) / 900.0;
    int indexX = int(floor(mod(float(pixelPos.x), 3.0))); 
    int indexY = int(floor(mod(float(pixelPos.y), 3.0))); 
    int index = indexX + indexY * 3; 
    int[9] a = { 3,7,4,6,1,9,2,8,5 }; // see Ordered Dithering on Wikipedia and elsewhere.
    vec4 targetColour = mix(colour1, colour2, alpha); 
    /* Do the dithering only when y > 200 so we can see a before and after. */
    if (pixelPos.y > 200) 
    {
        targetColour += float(a[index]) / 600.0;
        targetColour *= 0.95; // compensate for the slight increase in brightness. 
        targetColour.a = 1.0; // nail the alpha channel to 1.0
    }
    gl_FragColor = pixelAlpha * targetColour;
}

What was Vinnie getting at with 'your display has the wrong gamma'? I see banding on a range of displays when doing gradient fills over large areas using small transitions in colour.  Is this not typical?

There's probably a more efficent way of doing the OpenGL version (maybe using a texture map would avoid all those mod's and type conversions).

Anyway, results count.  Here's the output from shader.  You'll see the banding on the top half of the image, and the lovely banding free version below with a bit of luck. 

Jules - it'd be really nice to have a dither option on gradient fills that working with all the contexts, not just OpenGL.  Is that likely to ever happen or should I roll something myself?

1 Like