Qt World Summit: Register Today!

GLSL Chroma Key Shader like QML videofx example

  • Hi,
    I need to get a quick prototype up and running for a an app that can isolate a figure against a background, blue or green but could be other colors.

    I looked through the project examples and the QML video FX example is almost functional to rip out the parts I need into my existing QML-C++. I found out pretty quickly that I need to go down the GLSL shader route as my app will port also onto Android so needs realtime capability. The 'isolate' filter almost does what I need except it desaturates the color background instead of making it transparent, so I can put it over another image. Otherwise, everything I need is there and is easy to integrate. My issue is that I don't know much about GLSL and I'm pretty much taking a stab at the shader aspect at the moment. I have other working examples of very functional, opengl chroma key shaders for unity but I need to read up on GLSL before I can take a stab at integrating these. And I don't need a fully fledged, precision chroma key, just a reasonable result in reltime(ish) from camera or video - almost like the sample.

    Anyone any experience of this? The sample shader code is here, if some one can talk me through it and give me an idea of where to aim to change in for my purposes.

    Thank ever so much

    // Based on http://kodemongki.blogspot.com/2011/06/kameraku-custom-shader-effects-example.html

    uniform float targetHue;
    uniform float windowWidth;
    uniform float dividerValue;

    uniform sampler2D source;
    uniform lowp float qt_Opacity;
    varying vec2 qt_TexCoord0;

    void rgb2hsl(vec3 rgb, out float h, out float s, float l)
    float maxval = max(rgb.r, max(rgb.g, rgb.b));
    float minval = min(rgb.r, min(rgb.g, rgb.b));
    float delta = maxval - minval;
    l = (minval + maxval) / 2.0;
    s = 0.0;
    if (l > 0.0 && l < 1.0)
    s = delta / (l < 0.5 ? 2.0 * l : 2.0 - 2.0 * l);
    h = 0.0;
    if (delta > 0.0)
    if (rgb.r == maxval && rgb.g != maxval)
    h += (rgb.g - rgb.b ) / delta;
    if (rgb.g == maxval && rgb.b != maxval)
    h += 2.0 + (rgb.b - rgb.r) / delta;
    if (rgb.b == maxval && rgb.r != maxval)
    h += 4.0 + (rgb.r - rgb.g) / delta;
    h *= 60.0;

    void main()
    vec2 uv = qt_TexCoord0.xy;
    vec3 col = texture2D(source, uv).rgb;
    float h, s, l;
    rgb2hsl(col, h, s, l);
    float h2 = (h > targetHue) ? h - 360.0 : h + 360.0;
    float y = 0.3 * col.r + 0.59 * col.g + 0.11 * col.b;
    vec3 result;
    if (uv.x > dividerValue || (abs(h - targetHue) < windowWidth) || (abs(h2 - targetHue) < windowWidth))
    result = col;
    result = vec3(y, y, y);

    gl_FragColor = qt_Opacity * vec4(result, 1.0);


Log in to reply