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 } } } } } }
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…
> 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.