In the last example for custom shader effects, I would like to bring you the curtain effect. This effect was published first in May 2011 as part of Qt labs for shader effects.
At that time I really loved these effects and the curtain effect was my favorite out of them. I just love how the curtain opens and hide the background object.
For this chapter, the effect has been adapted for Qt 6. It has also been slghtly simplifed to make it a better showcase.
The curtain image is called fabric.png. The effect then uses a vertex shader to swing the curtain forth and back and a fragment shader to apply shadows to show how the fabric folds.
The diagram below shows how the shader works. The waves are computed through a sin curve with 7 periods (7*PI=21.99…). The other part is the swinging. The topWidht of the curtain is animated when the curtain is opened or closed. The bottomWidth follows the topWidth using a SpringAnimation. This creates the effect of the bottom part of the curtain swinging freely. The calulated swing component is the strengh of the swing based on the y-component of the vertexes.
The curtain effect is implemed in the CurtainEffect.qml file where the fabric image act as the texture source. In the QML code, the mesh property is adjusted to make sure that the number of vertixes is increased to give a smoother result.
The vertex shader, shown below, reshapes the curtain based on the topWidth and bottomWidth properies, extrapolating the shift based on the y-coordinate. It also calculates the shade value, which is used in the fragment shader. The shade property is passed through an additional output in location 1.
In the fragment shader below, the shade is picked up as an input in location 1 and is then used to calculate the fragColor, which is used to draw the pixel in question.
The combination of QML animations and passing variables from the vertex shader to the fragment shader demonstrates how QML and shaders can be used together to build complex, animated, effects.
The effect itself is used from the curtaindemo.qml file shown below.
The curtain is opened through a custom open property on the curtain effect. We use a MouseArea to trigger the opening and closing of the curtain when the user clicks or taps the area.