aboutsummaryrefslogtreecommitdiffstats
path: root/src/particles
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2013-10-26 18:48:56 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-10-31 12:54:28 +0100
commit426f6aa672b94d8324321bc6c6d4f1a358eebedc (patch)
tree8af3e5b0aa2fdcdb7655672669f5ae277151cc3d /src/particles
parent34c85bb56c92316a6ce1c79d25f9653fec14791c (diff)
Refactor shaders into seprate GLSL source files
The default implementation of QSGShaderMaterial::vertexShader() and fragmentShader() now loads the GLSL source from a list of source files that can be specified via the setShaderSourceFile() or setShaderSourceFiles() functions. Multiple shader source files for each shader stage are supported. Each source file will be read in the order specified and concatenated together before being compiled. The other places where Qt Quick 2 loads shader source code have been adapted to use the new QSGShaderSourceBuilder, which is also used internally by QSGMaterial. This puts Qt Quick 2 into a better state ready to support OpenGL core profile and to load different shaders based upon OpenGL version, profile, GPU vendor, platform, etc. Change-Id: I1a66213c2ce788413168eb48c7bc5317e61988a2 Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
Diffstat (limited to 'src/particles')
-rw-r--r--src/particles/particles.pri7
-rw-r--r--src/particles/particles.qrc7
-rw-r--r--src/particles/qquickcustomparticle.cpp53
-rw-r--r--src/particles/qquickimageparticle.cpp263
-rw-r--r--src/particles/shaders/customparticle.frag9
-rw-r--r--src/particles/shaders/customparticle.vert4
-rw-r--r--src/particles/shaders/customparticletemplate.vert26
-rw-r--r--src/particles/shaders/imageparticle.frag40
-rw-r--r--src/particles/shaders/imageparticle.vert143
9 files changed, 308 insertions, 244 deletions
diff --git a/src/particles/particles.pri b/src/particles/particles.pri
index 9b41a30d6b..b391050a58 100644
--- a/src/particles/particles.pri
+++ b/src/particles/particles.pri
@@ -63,6 +63,13 @@ SOURCES += \
$$PWD/qquickparticlegroup.cpp \
$$PWD/qquickgroupgoal.cpp
+OTHER_FILES += \
+ $$PWD/shaders/customparticletemplate.vert \
+ $$PWD/shaders/customparticle.vert \
+ $$PWD/shaders/customparticle.frag \
+ $$PWD/shaders/imageparticle.vert \
+ $$PWD/shaders/imageparticle.frag
+
RESOURCES += \
$$PWD/particles.qrc
diff --git a/src/particles/particles.qrc b/src/particles/particles.qrc
index 582520405f..689a5fb4e9 100644
--- a/src/particles/particles.qrc
+++ b/src/particles/particles.qrc
@@ -5,4 +5,11 @@
<file>particleresources/glowdot.png</file>
<file>particleresources/star.png</file>
</qresource>
+ <qresource prefix="/particles">
+ <file>shaders/customparticle.frag</file>
+ <file>shaders/customparticle.vert</file>
+ <file>shaders/customparticletemplate.vert</file>
+ <file>shaders/imageparticle.frag</file>
+ <file>shaders/imageparticle.vert</file>
+ </qresource>
</RCC>
diff --git a/src/particles/qquickcustomparticle.cpp b/src/particles/qquickcustomparticle.cpp
index 9bba3ebb18..71d58ae391 100644
--- a/src/particles/qquickcustomparticle.cpp
+++ b/src/particles/qquickcustomparticle.cpp
@@ -41,47 +41,11 @@
#include "qquickcustomparticle_p.h"
#include <QtQuick/private/qquickshadereffectmesh_p.h>
+#include <QtQuick/private/qsgshadersourcebuilder_p.h>
#include <cstdlib>
QT_BEGIN_NAMESPACE
-//Includes comments because the code isn't self explanatory
-static const char qt_particles_template_vertex_code[] =
- "attribute highp vec2 qt_ParticlePos;\n"
- "attribute highp vec2 qt_ParticleTex;\n"
- "attribute highp vec4 qt_ParticleData; // x = time, y = lifeSpan, z = size, w = endSize\n"
- "attribute highp vec4 qt_ParticleVec; // x,y = constant velocity, z,w = acceleration\n"
- "attribute highp float qt_ParticleR;\n"
- "uniform highp mat4 qt_Matrix;\n"
- "uniform highp float qt_Timestamp;\n"
- "varying highp vec2 qt_TexCoord0;\n"
- "void defaultMain() {\n"
- " qt_TexCoord0 = qt_ParticleTex;\n"
- " highp float size = qt_ParticleData.z;\n"
- " highp float endSize = qt_ParticleData.w;\n"
- " highp float t = (qt_Timestamp - qt_ParticleData.x) / qt_ParticleData.y;\n"
- " highp float currentSize = mix(size, endSize, t * t);\n"
- " if (t < 0. || t > 1.)\n"
- " currentSize = 0.;\n"
- " highp vec2 pos = qt_ParticlePos\n"
- " - currentSize / 2. + currentSize * qt_ParticleTex // adjust size\n"
- " + qt_ParticleVec.xy * t * qt_ParticleData.y // apply velocity vector..\n"
- " + 0.5 * qt_ParticleVec.zw * pow(t * qt_ParticleData.y, 2.);\n"
- " gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);\n"
- "}";
-static const char qt_particles_default_vertex_code[] =
- "void main() { \n"
- " defaultMain(); \n"
- "}";
-
-static const char qt_particles_default_fragment_code[] =
- "uniform sampler2D source; \n"
- "varying highp vec2 qt_TexCoord0; \n"
- "uniform lowp float qt_Opacity; \n"
- "void main() { \n"
- " gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity; \n"
- "}";
-
static QSGGeometry::Attribute PlainParticle_Attributes[] = {
QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // Position
QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // TexCoord
@@ -309,11 +273,18 @@ QQuickShaderEffectNode *QQuickCustomParticle::prepareNextFrame(QQuickShaderEffec
Q_ASSERT(material);
Key s = m_common.source;
- if (s.sourceCode[Key::FragmentShader].isEmpty())
- s.sourceCode[Key::FragmentShader] = qt_particles_default_fragment_code;
+ QSGShaderSourceBuilder builder;
+ if (s.sourceCode[Key::FragmentShader].isEmpty()) {
+ builder.appendSourceFile(QStringLiteral(":/particles/shaders/customparticle.frag"));
+ s.sourceCode[Key::FragmentShader] = builder.source();
+ builder.clear();
+ }
+
+ builder.appendSourceFile(QStringLiteral(":/particles/shaders/customparticletemplate.vert"));
if (s.sourceCode[Key::VertexShader].isEmpty())
- s.sourceCode[Key::VertexShader] = qt_particles_default_vertex_code;
- s.sourceCode[Key::VertexShader] = qt_particles_template_vertex_code + s.sourceCode[Key::VertexShader];
+ builder.appendSourceFile(QStringLiteral(":/particles/shaders/customparticle.vert"));
+ s.sourceCode[Key::VertexShader] = builder.source() + s.sourceCode[Key::VertexShader];
+
s.className = metaObject()->className();
material->setProgramSource(s);
diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp
index 01cd487664..baaae86870 100644
--- a/src/particles/qquickimageparticle.cpp
+++ b/src/particles/qquickimageparticle.cpp
@@ -51,6 +51,7 @@
#include <private/qquicksprite_p.h>
#include <private/qquickspriteengine_p.h>
#include <QOpenGLFunctions>
+#include <QtQuick/private/qsgshadersourcebuilder_p.h>
#include <QtQuick/private/qsgtexture_p.h>
#include <private/qqmlglobal_p.h>
#include <QtQml/qqmlinfo.h>
@@ -64,183 +65,14 @@ QT_BEGIN_NAMESPACE
#define SHADER_DEFINES ""
#endif
-//TODO: Make it larger on desktop? Requires fixing up shader code with the same define
-#define UNIFORM_ARRAY_SIZE 64
-
-static const char vertexShaderCode[] =
- "#if defined(DEFORM)\n"
- "attribute highp vec4 vPosTex;\n"
- "#else\n"
- "attribute highp vec2 vPos;\n"
- "#endif\n"
- "attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize\n"
- "attribute highp vec4 vVec; // x,y = constant velocity, z,w = acceleration\n"
- "uniform highp float entry;\n"
- "#if defined(COLOR)\n"
- "attribute highp vec4 vColor;\n"
- "#endif\n"
- "#if defined(DEFORM)\n"
- "attribute highp vec4 vDeformVec; //x,y x unit vector; z,w = y unit vector\n"
- "attribute highp vec3 vRotation; //x = radians of rotation, y=rotation velocity, z= bool autoRotate\n"
- "#endif\n"
- "#if defined(SPRITE)\n"
- "attribute highp vec3 vAnimData;// w,h(premultiplied of anim), interpolation progress\n"
- "attribute highp vec4 vAnimPos;//x,y, x,y (two frames for interpolation)\n"
- "#endif\n"
- "\n"
- "uniform highp mat4 qt_Matrix;\n"
- "uniform highp float timestamp;\n"
- "#if defined(TABLE)\n"
- "varying lowp vec2 tt;//y is progress if Sprite mode\n"
- "uniform highp float sizetable[64];\n"
- "uniform highp float opacitytable[64];\n"
- "#endif\n"
- "#if defined(SPRITE)\n"
- "varying highp vec4 fTexS;\n"
- "#elif defined(DEFORM)\n"
- "varying highp vec2 fTex;\n"
- "#endif\n"
- "#if defined(COLOR)\n"
- "varying lowp vec4 fColor;\n"
- "#else\n"
- "varying lowp float fFade;\n"
- "#endif\n"
- "\n"
- "\n"
- "void main() {\n"
- "\n"
- " highp float t = (timestamp - vData.x) / vData.y;\n"
- " if (t < 0. || t > 1.) {\n"
- "#if defined(DEFORM)\n"
- " gl_Position = qt_Matrix * vec4(vPosTex.x, vPosTex.y, 0., 1.);\n"
- "#else\n"
- " gl_PointSize = 0.;\n"
- "#endif\n"
- " } else {\n"
- "#if defined(SPRITE)\n"
- " tt.y = vAnimData.z;\n"
- " //Calculate frame location in texture\n"
- " fTexS.xy = vAnimPos.xy + vPosTex.zw * vAnimData.xy;\n"
- " //Next frame is also passed, for interpolation\n"
- " fTexS.zw = vAnimPos.zw + vPosTex.zw * vAnimData.xy;\n"
- "\n"
- "#elif defined(DEFORM)\n"
- " fTex = vPosTex.zw;\n"
- "#endif\n"
- " highp float currentSize = mix(vData.z, vData.w, t * t);\n"
-#if defined (Q_OS_BLACKBERRY)
- " highp float fade = 1.;\n"
+#if defined(Q_OS_BLACKBERRY)
+#define SHADER_PLATFORM_DEFINES "#define Q_OS_BLACKBERRY\n"
#else
- " lowp float fade = 1.;\n"
+#define SHADER_PLATFORM_DEFINES
#endif
- " highp float fadeIn = min(t * 10., 1.);\n"
- " highp float fadeOut = 1. - clamp((t - 0.75) * 4.,0., 1.);\n"
- "\n"
- "#if defined(TABLE)\n"
- " currentSize = currentSize * sizetable[int(floor(t*64.))];\n"
- " fade = fade * opacitytable[int(floor(t*64.))];\n"
- "#endif\n"
- "\n"
- " if (entry == 1.)\n"
- " fade = fade * fadeIn * fadeOut;\n"
- " else if (entry == 2.)\n"
- " currentSize = currentSize * fadeIn * fadeOut;\n"
- "\n"
- " if (currentSize <= 0.) {\n"
- "#if defined(DEFORM)\n"
- " gl_Position = qt_Matrix * vec4(vPosTex.x, vPosTex.y, 0., 1.);\n"
- "#else\n"
- " gl_PointSize = 0.;\n"
- "#endif\n"
- " } else {\n"
- " if (currentSize < 3.)//Sizes too small look jittery as they move\n"
- " currentSize = 3.;\n"
- "\n"
- " highp vec2 pos;\n"
- "#if defined(DEFORM)\n"
- " highp float rotation = vRotation.x + vRotation.y * t * vData.y;\n"
- " if (vRotation.z == 1.0){\n"
- " highp vec2 curVel = vVec.zw * t * vData.y + vVec.xy;\n"
- " if (length(curVel) > 0.)\n"
- " rotation += atan(curVel.y, curVel.x);\n"
- " }\n"
- " highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation));\n"
- " highp vec4 deform = vDeformVec * currentSize * (vPosTex.zzww - 0.5);\n"
- " highp vec4 rotatedDeform = deform.xxzz * trigCalcs.xyxy;\n"
- " rotatedDeform = rotatedDeform + (deform.yyww * trigCalcs.yxyx * vec4(-1.,1.,-1.,1.));\n"
- " /* The readable version:\n"
- " highp vec2 xDeform = vDeformVec.xy * currentSize * (vTex.x-0.5);\n"
- " highp vec2 yDeform = vDeformVec.zw * currentSize * (vTex.y-0.5);\n"
- " highp vec2 xRotatedDeform;\n"
- " xRotatedDeform.x = trigCalcs.x*xDeform.x - trigCalcs.y*xDeform.y;\n"
- " xRotatedDeform.y = trigCalcs.y*xDeform.x + trigCalcs.x*xDeform.y;\n"
- " highp vec2 yRotatedDeform;\n"
- " yRotatedDeform.x = trigCalcs.x*yDeform.x - trigCalcs.y*yDeform.y;\n"
- " yRotatedDeform.y = trigCalcs.y*yDeform.x + trigCalcs.x*yDeform.y;\n"
- " */\n"
- " pos = vPosTex.xy\n"
- " + rotatedDeform.xy\n"
- " + rotatedDeform.zw\n"
- " + vVec.xy * t * vData.y // apply velocity\n"
- " + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration\n"
- "#else\n"
- " pos = vPos\n"
- " + vVec.xy * t * vData.y // apply velocity vector..\n"
- " + 0.5 * vVec.zw * pow(t * vData.y, 2.);\n"
- " gl_PointSize = currentSize;\n"
- "#endif\n"
- " gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);\n"
- "\n"
- "#if defined(COLOR)\n"
- " fColor = vColor * fade;\n"
- "#else\n"
- " fFade = fade;\n"
- "#endif\n"
- "#if defined(TABLE)\n"
- " tt.x = t;\n"
- "#endif\n"
- " }\n"
- " }\n"
- "}\n";
-
-static const char fragmentShaderCode[] =
- "uniform sampler2D _qt_texture;\n"
- "uniform lowp float qt_Opacity;\n"
- "\n"
- "#if defined(SPRITE)\n"
- "varying highp vec4 fTexS;\n"
- "#elif defined(DEFORM)\n"
- "varying highp vec2 fTex;\n"
- "#endif\n"
- "#if defined(COLOR)\n"
- "varying lowp vec4 fColor;\n"
- "#else\n"
- "varying lowp float fFade;\n"
- "#endif\n"
- "#if defined(TABLE)\n"
- "varying lowp vec2 tt;\n"
- "uniform sampler2D colortable;\n"
- "#endif\n"
- "\n"
- "void main() {\n"
- "#if defined(SPRITE)\n"
- " gl_FragColor = mix(texture2D(_qt_texture, fTexS.xy), texture2D(_qt_texture, fTexS.zw), tt.y)\n"
- " * fColor\n"
- " * texture2D(colortable, tt)\n"
- " * qt_Opacity;\n"
- "#elif defined(TABLE)\n"
- " gl_FragColor = texture2D(_qt_texture, fTex)\n"
- " * fColor\n"
- " * texture2D(colortable, tt)\n"
- " * qt_Opacity;\n"
- "#elif defined(DEFORM)\n"
- " gl_FragColor = (texture2D(_qt_texture, fTex)) * fColor * qt_Opacity;\n"
- "#elif defined(COLOR)\n"
- " gl_FragColor = (texture2D(_qt_texture, gl_PointCoord)) * fColor * qt_Opacity;\n"
- "#else\n"
- " gl_FragColor = texture2D(_qt_texture, gl_PointCoord) * (fFade * qt_Opacity);\n"
- "#endif\n"
- "}\n";
+
+//TODO: Make it larger on desktop? Requires fixing up shader code with the same define
+#define UNIFORM_ARRAY_SIZE 64
const qreal CONV = 0.017453292519943295;
class ImageMaterialData
@@ -273,13 +105,18 @@ class TabledMaterial : public QSGSimpleMaterialShader<TabledMaterialData>
public:
TabledMaterial()
{
- m_vertex_code = QByteArray(SHADER_DEFINES)
- + QByteArray("#define TABLE\n#define DEFORM\n#define COLOR\n")
- + vertexShaderCode;
+ QSGShaderSourceBuilder builder;
- m_fragment_code = QByteArray(SHADER_DEFINES)
- + QByteArray("#define TABLE\n#define DEFORM\n#define COLOR\n")
- + fragmentShaderCode;
+ builder.appendSource(QByteArray(SHADER_DEFINES) + QByteArray(SHADER_PLATFORM_DEFINES));
+ builder.appendSource(QByteArray("#define TABLE\n#define DEFORM\n#define COLOR\n"));
+ builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert"));
+ m_vertex_code = builder.source();
+ builder.clear();
+
+ builder.appendSource(QByteArray(SHADER_DEFINES));
+ builder.appendSource(QByteArray("#define TABLE\n#define DEFORM\n#define COLOR\n"));
+ builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag"));
+ m_fragment_code = builder.source();
Q_ASSERT(!m_vertex_code.isNull());
Q_ASSERT(!m_fragment_code.isNull());
@@ -335,13 +172,18 @@ class DeformableMaterial : public QSGSimpleMaterialShader<DeformableMaterialData
public:
DeformableMaterial()
{
- m_vertex_code = QByteArray(SHADER_DEFINES)
- + QByteArray("#define DEFORM\n#define COLOR\n")
- + vertexShaderCode;
+ QSGShaderSourceBuilder builder;
+
+ builder.appendSource(QByteArray(SHADER_DEFINES) + QByteArray(SHADER_PLATFORM_DEFINES));
+ builder.appendSource(QByteArray("#define DEFORM\n#define COLOR\n"));
+ builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert"));
+ m_vertex_code = builder.source();
+ builder.clear();
- m_fragment_code = QByteArray(SHADER_DEFINES)
- + QByteArray("#define DEFORM\n#define COLOR\n")
- + fragmentShaderCode;
+ builder.appendSource(QByteArray(SHADER_DEFINES));
+ builder.appendSource(QByteArray("#define DEFORM\n#define COLOR\n"));
+ builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag"));
+ m_fragment_code = builder.source();
Q_ASSERT(!m_vertex_code.isNull());
Q_ASSERT(!m_fragment_code.isNull());
@@ -386,13 +228,18 @@ class SpriteMaterial : public QSGSimpleMaterialShader<SpriteMaterialData>
public:
SpriteMaterial()
{
- m_vertex_code = QByteArray(SHADER_DEFINES)
- + QByteArray("#define SPRITE\n#define TABLE\n#define DEFORM\n#define COLOR\n")
- + vertexShaderCode;
+ QSGShaderSourceBuilder builder;
+
+ builder.appendSource(QByteArray(SHADER_DEFINES) + QByteArray(SHADER_PLATFORM_DEFINES));
+ builder.appendSource(QByteArray("#define SPRITE\n#define TABLE\n#define DEFORM\n#define COLOR\n"));
+ builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert"));
+ m_vertex_code = builder.source();
+ builder.clear();
- m_fragment_code = QByteArray(SHADER_DEFINES)
- + QByteArray("#define SPRITE\n#define TABLE\n#define DEFORM\n#define COLOR\n")
- + fragmentShaderCode;
+ builder.appendSource(QByteArray(SHADER_DEFINES));
+ builder.appendSource(QByteArray("#define SPRITE\n#define TABLE\n#define DEFORM\n#define COLOR\n"));
+ builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag"));
+ m_fragment_code = builder.source();
Q_ASSERT(!m_vertex_code.isNull());
Q_ASSERT(!m_fragment_code.isNull());
@@ -450,13 +297,18 @@ class ColoredMaterial : public QSGSimpleMaterialShader<ColoredMaterialData>
public:
ColoredMaterial()
{
- m_vertex_code = QByteArray(SHADER_DEFINES)
- + QByteArray("#define COLOR\n")
- + vertexShaderCode;
+ QSGShaderSourceBuilder builder;
- m_fragment_code = QByteArray(SHADER_DEFINES)
- + QByteArray("#define COLOR\n")
- + fragmentShaderCode;
+ builder.appendSource(QByteArray(SHADER_DEFINES) + QByteArray(SHADER_PLATFORM_DEFINES));
+ builder.appendSource(QByteArray("#define COLOR\n"));
+ builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert"));
+ m_vertex_code = builder.source();
+ builder.clear();
+
+ builder.appendSource(QByteArray(SHADER_DEFINES));
+ builder.appendSource(QByteArray("#define COLOR\n"));
+ builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag"));
+ m_fragment_code = builder.source();
Q_ASSERT(!m_vertex_code.isNull());
Q_ASSERT(!m_fragment_code.isNull());
@@ -516,11 +368,16 @@ class SimpleMaterial : public QSGSimpleMaterialShader<SimpleMaterialData>
public:
SimpleMaterial()
{
- m_vertex_code = QByteArray(SHADER_DEFINES)
- + vertexShaderCode;
+ QSGShaderSourceBuilder builder;
+
+ builder.appendSource(QByteArray(SHADER_DEFINES) + QByteArray(SHADER_PLATFORM_DEFINES));
+ builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert"));
+ m_vertex_code = builder.source();
+ builder.clear();
- m_fragment_code = QByteArray(SHADER_DEFINES)
- + fragmentShaderCode;
+ builder.appendSource(QByteArray(SHADER_DEFINES));
+ builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag"));
+ m_fragment_code = builder.source();
Q_ASSERT(!m_vertex_code.isNull());
Q_ASSERT(!m_fragment_code.isNull());
diff --git a/src/particles/shaders/customparticle.frag b/src/particles/shaders/customparticle.frag
new file mode 100644
index 0000000000..c1c15ecb0c
--- /dev/null
+++ b/src/particles/shaders/customparticle.frag
@@ -0,0 +1,9 @@
+varying highp vec2 qt_TexCoord0;
+
+uniform sampler2D source;
+uniform lowp float qt_Opacity;
+
+void main()
+{
+ gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity;
+} \ No newline at end of file
diff --git a/src/particles/shaders/customparticle.vert b/src/particles/shaders/customparticle.vert
new file mode 100644
index 0000000000..b99f73ea53
--- /dev/null
+++ b/src/particles/shaders/customparticle.vert
@@ -0,0 +1,4 @@
+void main()
+{
+ defaultMain();
+} \ No newline at end of file
diff --git a/src/particles/shaders/customparticletemplate.vert b/src/particles/shaders/customparticletemplate.vert
new file mode 100644
index 0000000000..c482c4207b
--- /dev/null
+++ b/src/particles/shaders/customparticletemplate.vert
@@ -0,0 +1,26 @@
+attribute highp vec2 qt_ParticlePos;
+attribute highp vec2 qt_ParticleTex;
+attribute highp vec4 qt_ParticleData; // x = time, y = lifeSpan, z = size, w = endSize
+attribute highp vec4 qt_ParticleVec; // x,y = constant velocity, z,w = acceleration
+attribute highp float qt_ParticleR;
+
+uniform highp mat4 qt_Matrix;
+uniform highp float qt_Timestamp;
+
+varying highp vec2 qt_TexCoord0;
+
+void defaultMain()
+{
+ qt_TexCoord0 = qt_ParticleTex;
+ highp float size = qt_ParticleData.z;
+ highp float endSize = qt_ParticleData.w;
+ highp float t = (qt_Timestamp - qt_ParticleData.x) / qt_ParticleData.y;
+ highp float currentSize = mix(size, endSize, t * t);
+ if (t < 0. || t > 1.)
+ currentSize = 0.;
+ highp vec2 pos = qt_ParticlePos
+ - currentSize / 2. + currentSize * qt_ParticleTex // adjust size
+ + qt_ParticleVec.xy * t * qt_ParticleData.y // apply velocity vector..
+ + 0.5 * qt_ParticleVec.zw * pow(t * qt_ParticleData.y, 2.);
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
+}
diff --git a/src/particles/shaders/imageparticle.frag b/src/particles/shaders/imageparticle.frag
new file mode 100644
index 0000000000..699b90babf
--- /dev/null
+++ b/src/particles/shaders/imageparticle.frag
@@ -0,0 +1,40 @@
+uniform sampler2D _qt_texture;
+uniform lowp float qt_Opacity;
+
+#if defined(SPRITE)
+varying highp vec4 fTexS;
+#elif defined(DEFORM)
+varying highp vec2 fTex;
+#endif
+
+#if defined(COLOR)
+varying lowp vec4 fColor;
+#else
+varying lowp float fFade;
+#endif
+
+#if defined(TABLE)
+varying lowp vec2 tt;
+uniform sampler2D colortable;
+#endif
+
+void main()
+{
+#if defined(SPRITE)
+ gl_FragColor = mix(texture2D(_qt_texture, fTexS.xy), texture2D(_qt_texture, fTexS.zw), tt.y)
+ * fColor
+ * texture2D(colortable, tt)
+ * qt_Opacity;
+#elif defined(TABLE)
+ gl_FragColor = texture2D(_qt_texture, fTex)
+ * fColor
+ * texture2D(colortable, tt)
+ * qt_Opacity;
+#elif defined(DEFORM)
+ gl_FragColor = (texture2D(_qt_texture, fTex)) * fColor * qt_Opacity;
+#elif defined(COLOR)
+ gl_FragColor = (texture2D(_qt_texture, gl_PointCoord)) * fColor * qt_Opacity;
+#else
+ gl_FragColor = texture2D(_qt_texture, gl_PointCoord) * (fFade * qt_Opacity);
+#endif
+} \ No newline at end of file
diff --git a/src/particles/shaders/imageparticle.vert b/src/particles/shaders/imageparticle.vert
new file mode 100644
index 0000000000..9e607a7477
--- /dev/null
+++ b/src/particles/shaders/imageparticle.vert
@@ -0,0 +1,143 @@
+#if defined(DEFORM)
+attribute highp vec4 vPosTex;
+#else
+attribute highp vec2 vPos;
+#endif
+
+attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
+attribute highp vec4 vVec; // x,y = constant velocity, z,w = acceleration
+uniform highp float entry;
+
+#if defined(COLOR)
+attribute highp vec4 vColor;
+#endif
+
+#if defined(DEFORM)
+attribute highp vec4 vDeformVec; // x,y x unit vector; z,w = y unit vector
+attribute highp vec3 vRotation; // x = radians of rotation, y = rotation velocity, z = bool autoRotate
+#endif
+
+#if defined(SPRITE)
+attribute highp vec3 vAnimData; // w,h(premultiplied of anim), interpolation progress
+attribute highp vec4 vAnimPos; // x,y, x,y (two frames for interpolation)
+#endif
+
+uniform highp mat4 qt_Matrix;
+uniform highp float timestamp;
+
+#if defined(TABLE)
+varying lowp vec2 tt;//y is progress if Sprite mode
+uniform highp float sizetable[64];
+uniform highp float opacitytable[64];
+#endif
+
+#if defined(SPRITE)
+varying highp vec4 fTexS;
+#elif defined(DEFORM)
+varying highp vec2 fTex;
+#endif
+
+#if defined(COLOR)
+varying lowp vec4 fColor;
+#else
+varying lowp float fFade;
+#endif
+
+
+void main()
+{
+ highp float t = (timestamp - vData.x) / vData.y;
+ if (t < 0. || t > 1.) {
+#if defined(DEFORM)
+ gl_Position = qt_Matrix * vec4(vPosTex.x, vPosTex.y, 0., 1.);
+#else
+ gl_PointSize = 0.;
+#endif
+ } else {
+#if defined(SPRITE)
+ tt.y = vAnimData.z;
+
+ // Calculate frame location in texture
+ fTexS.xy = vAnimPos.xy + vPosTex.zw * vAnimData.xy;
+
+ // Next frame is also passed, for interpolation
+ fTexS.zw = vAnimPos.zw + vPosTex.zw * vAnimData.xy;
+
+#elif defined(DEFORM)
+ fTex = vPosTex.zw;
+#endif
+ highp float currentSize = mix(vData.z, vData.w, t * t);
+#if defined (Q_OS_BLACKBERRY)
+ highp float fade = 1.;
+#else
+ lowp float fade = 1.;
+#endif
+ highp float fadeIn = min(t * 10., 1.);
+ highp float fadeOut = 1. - clamp((t - 0.75) * 4.,0., 1.);
+
+#if defined(TABLE)
+ currentSize = currentSize * sizetable[int(floor(t*64.))];
+ fade = fade * opacitytable[int(floor(t*64.))];
+#endif
+
+ if (entry == 1.)
+ fade = fade * fadeIn * fadeOut;
+ else if (entry == 2.)
+ currentSize = currentSize * fadeIn * fadeOut;
+
+ if (currentSize <= 0.) {
+#if defined(DEFORM)
+ gl_Position = qt_Matrix * vec4(vPosTex.x, vPosTex.y, 0., 1.);
+#else
+ gl_PointSize = 0.;
+#endif
+ } else {
+ if (currentSize < 3.) // Sizes too small look jittery as they move
+ currentSize = 3.;
+
+ highp vec2 pos;
+#if defined(DEFORM)
+ highp float rotation = vRotation.x + vRotation.y * t * vData.y;
+ if (vRotation.z == 1.0){
+ highp vec2 curVel = vVec.zw * t * vData.y + vVec.xy;
+ if (length(curVel) > 0.)
+ rotation += atan(curVel.y, curVel.x);
+ }
+ highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation));
+ highp vec4 deform = vDeformVec * currentSize * (vPosTex.zzww - 0.5);
+ highp vec4 rotatedDeform = deform.xxzz * trigCalcs.xyxy;
+ rotatedDeform = rotatedDeform + (deform.yyww * trigCalcs.yxyx * vec4(-1.,1.,-1.,1.));
+ /* The readable version:
+ highp vec2 xDeform = vDeformVec.xy * currentSize * (vTex.x-0.5);
+ highp vec2 yDeform = vDeformVec.zw * currentSize * (vTex.y-0.5);
+ highp vec2 xRotatedDeform;
+ xRotatedDeform.x = trigCalcs.x*xDeform.x - trigCalcs.y*xDeform.y;
+ xRotatedDeform.y = trigCalcs.y*xDeform.x + trigCalcs.x*xDeform.y;
+ highp vec2 yRotatedDeform;
+ yRotatedDeform.x = trigCalcs.x*yDeform.x - trigCalcs.y*yDeform.y;
+ yRotatedDeform.y = trigCalcs.y*yDeform.x + trigCalcs.x*yDeform.y;
+ */
+ pos = vPosTex.xy
+ + rotatedDeform.xy
+ + rotatedDeform.zw
+ + vVec.xy * t * vData.y // apply velocity
+ + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration
+#else
+ pos = vPos
+ + vVec.xy * t * vData.y // apply velocity vector..
+ + 0.5 * vVec.zw * pow(t * vData.y, 2.);
+ gl_PointSize = currentSize;
+#endif
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
+
+#if defined(COLOR)
+ fColor = vColor * fade;
+#else
+ fFade = fade;
+#endif
+#if defined(TABLE)
+ tt.x = t;
+#endif
+ }
+ }
+} \ No newline at end of file