Live Pixels

Last weekend I started playing with the new Qt 5 particle effect system. One interesting effect I found in the examples was using custom particles and OpenGL shaders to color the moving particles, producing a cool-looking image on the screen made of “live” pixels. For this blog entry I have drawn an image of a skull, which in the example gets rotated and scaled across easing curves to further enhance the effect and finally fed to the particle system.

The original drawing with and without the effect
Show code ยป

livepixels.qml:

import QtQuick 2.0
import QtQuick.Particles 2.0

Rectangle{
    width: 800; height: 480
    ParticleSystem {
        width: image.width
        height: image.height
        anchors.centerIn: parent
        Emitter {
            size: 15
            sizeVariation: 10
            speed: PointDirection { xVariation: 8; yVariation: 8 }
            emitRate: 10000
            lifeSpan: 2000
            anchors.fill: parent
        }
        CustomParticle {
            property real maxWidth: parent.width
            property real maxHeight: parent.height
            property variant particleTexture: ShaderEffectSource {
                sourceItem: Image { source: "particle.png" }
                hideSource: true
            }
            property variant pictureTexture: ShaderEffectSource {
                sourceItem: sourceImage
                hideSource: true
                live: true
            }
            vertexShader:"
                uniform highp float maxWidth;
                uniform highp float maxHeight;
                varying highp vec2 fTex2;
                varying lowp float fFade;
                uniform lowp float qt_Opacity;

                void main() {
                    fTex2 = vec2(qt_ParticlePos.x / maxWidth, qt_ParticlePos.y / maxHeight);
                    highp float t = (qt_Timestamp - qt_ParticleData.x) / qt_ParticleData.y;
                    fFade = min(t*4., (1.-t*t)*.75) * qt_Opacity;
                    defaultMain();
                }
            "
            fragmentShader: "
                uniform sampler2D particleTexture;
                uniform sampler2D pictureTexture;
                varying highp vec2 qt_TexCoord0;
                varying highp vec2 fTex2;
                varying lowp float fFade;
                void main() {
                    gl_FragColor = texture2D(pictureTexture, fTex2) * texture2D(particleTexture, qt_TexCoord0).w * fFade;
            }"
        }
    }
    Item {
        id: sourceImage
        width: image.width; height: image.height
        anchors.centerIn: parent
        Image{
            id: image
            source: "skull.png"
            scale: 1 + 0.15*Math.random()
            Behavior on scale {
                NumberAnimation { duration: 3000; easing.type: Easing.InOutQuad }
            }
            Timer {
                interval: 3000
                repeat: true; running: true
                onTriggered: parent.scale = 1 + 0.15*Math.random()
            }
            transform: Rotation {
                id: rotation
                property real value: Math.random()
                property bool reverse: Math.random() > 0.5
                origin.x: image.width/2; origin.y: image.height/2
                axis.x: Math.random() < 0.2 || value < 0.5
                axis.y: Math.random() < 0.2 || value >= 0.5
                SequentialAnimation on angle {
                    loops: Animation.Infinite
                    NumberAnimation {
                        from: 0.0; to: rotation.reverse ? -8.0 : 8.0
                        duration: 2500; easing.type: Easing.InOutQuad
                    }
                    NumberAnimation {
                        from: rotation.reverse ? -8.0 : 8.0; to: 0.0
                        duration: 2500; easing.type: Easing.InOutQuad
                    }
                }
            }
        }
    }
}

2 thoughts on “Live Pixels”

  1. Nice example about using particle effect system!

    btw, would it be possible to have the live pixels effect only affecting to certain part of an image at a time (and even changing the effect area on the fly)?

    Expecting to see more nice examples/demos…

  2. > Would it be possible to have the live pixels effect only affecting to certain part of an image at a time?

    Yes, for example by feeding the result into a mask shader and changing the masking area on the fly or somehow combining particle shader and masking functionality together in one shader program.

Leave a Reply

Your email address will not be published.