Fragment Shaders

    First, we set up our scene, with a grid centered in the field and our source image be displayed.

    A red shader

    Next, we will add a shader, which displays a red rectangle by providing for each fragment a red color value.

    1. layout(location=0) in vec2 qt_TexCoord0;
    2. layout(location=0) out vec4 fragColor;
    3. layout(std140, binding=0) uniform buf {
    4. float qt_Opacity;
    5. } ubuf;
    6. layout(binding=1) uniform sampler2D source;
    7. void main() {
    8. fragColor = vec4(1.0, 0.0, 0.0, 1.0) * ubuf.qt_Opacity;
    9. }

    In the fragment shader we simply assign a , representing the color red with full opacity (alpha=1.0), to the fragColor for each fragment, turning each pixel to a solid red.

    image

    The full shader contains now back our image source as variant property and we have left out the vertex shader, which if not specified is the default vertex shader.

    In the fragment shader, we pick the texture fragment texture(source, qt_TexCoord0) and apply the red color to it.

    The red channel property

    It’s not really nice to hard code the red channel value, so we would like to control the value from the QML side. For this we add a redChannel property to our shader effect and also declare a float redChannel inside the uniform buffer of the fragment shader. That is all that we need to do to make a value from the QML side available to the shader code.

    TIP

    1. #version 440
    2. layout(location=0) in vec2 qt_TexCoord0;
    3. layout(location=0) out vec4 fragColor;
    4. layout(std140, binding=0) uniform buf {
    5. mat4 qt_Matrix;
    6. float qt_Opacity;
    7. float redChannel;
    8. } ubuf;
    9. layout(binding=1) uniform sampler2D source;
    10. void main() {
    11. fragColor = texture(source, qt_TexCoord0) * vec4(ubuf.redChannel, 1.0, 1.0, 1.0) * ubuf.qt_Opacity;
    12. }

    To make the lens really a lens, we change the vec4 color to be vec4(redChannel, 1.0, 1.0, 1.0) so that the other colors are multiplied by 1.0 and only the red portion is multiplied by our redChannel variable.

    image

    As the redChannel property is just a normal property it can also be animated as all properties in QML. So we can use QML properties to animate values on the GPU to influence our shaders. How cool is that!

    Here the final result.

    Baking

    Again, we need to bake the shaders. The following commands from the command line does that:

    1. qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -o red1.frag.qsb red1.frag
    2. qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -o red3.frag.qsb red3.frag