Switch from textures to uniform arrays for size/opacity tables
authorAlan Alpert <alan.alpert@nokia.com>
Tue, 23 Aug 2011 08:20:58 +0000 (18:20 +1000)
committerQt by Nokia <qt-info@nokia.com>
Wed, 24 Aug 2011 08:11:29 +0000 (10:11 +0200)
Change-Id: Iafc5eaa80f68345cc3b14fe0b2d997c1af435419
Reviewed-on: http://codereview.qt.nokia.com/3388
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Alan Alpert <alan.alpert@nokia.com>
src/declarative/particles/defaultshaders/imagefragment.shader
src/declarative/particles/defaultshaders/imagevertex.shader
src/declarative/particles/qsgimageparticle.cpp
src/declarative/particles/qsgpointattractor_p.h

index 5286c85..c2341fe 100644 (file)
@@ -16,8 +16,6 @@ varying lowp float fFade;
 #ifdef TABLE
 varying lowp vec2 tt;
 uniform sampler2D colortable;
-uniform sampler2D opacitytable;
-uniform sampler2D sizetable;
 #endif
 
 void main() {
@@ -25,20 +23,13 @@ void main() {
     gl_FragColor = mix(texture2D(texture, fTexS.xy), texture2D(texture, fTexS.zw), tt.y)
             * fColor
             * texture2D(colortable, tt)
-            * (texture2D(opacitytable, tt).w * qt_Opacity);
+            * qt_Opacity;
 #else
 #ifdef TABLE
-    highp vec2 tex = (((fTex - 0.5) / texture2D(sizetable, tt).w) + 0.5);
-    lowp vec4 color;
-    if(tex.x < 1.0 && tex.x > 0.0 && tex.y < 1.0 && tex.y > 0.0){//No CLAMP_TO_BORDER in ES2, so have to do it ourselves
-        color = texture2D(texture, tex);//TODO: Replace with uniform array in vertex shader
-    }else{
-        color = vec4(0.,0.,0.,0.);
-    }
-    gl_FragColor = color
+    gl_FragColor = texture2D(texture, fTex)
             * fColor
             * texture2D(colortable, tt)
-            * (texture2D(opacitytable,tt).w * qt_Opacity);
+            * qt_Opacity;
 #else
 #ifdef DEFORM
     gl_FragColor = (texture2D(texture, fTex)) * fColor * qt_Opacity;
index a572d73..e1033c9 100644 (file)
@@ -20,6 +20,8 @@ uniform highp mat4 qt_Matrix;
 uniform highp float timestamp;
 #ifdef TABLE
 varying lowp vec2 tt;//y is progress if Sprite mode
+uniform highp float sizetable[64];
+uniform highp float opacitytable[64];
 #endif
 #ifdef SPRITE
 varying highp vec4 fTexS;
@@ -69,6 +71,10 @@ void main() {
     highp float fadeIn = min(t * 10., 1.);
     highp float fadeOut = 1. - clamp((t - 0.75) * 4.,0., 1.);
 
+#ifdef TABLE
+    currentSize = currentSize * sizetable[int(floor(t*64.))];
+    fade = fade * opacitytable[int(floor(t*64.))];
+#endif
     if (entry == 1.)
         fade = fadeIn * fadeOut;
     else if(entry == 2.)
index f2fb289..3b58bfc 100644 (file)
@@ -62,25 +62,27 @@ DEFINE_BOOL_CONFIG_OPTION(qmlParticlesDebug, QML_PARTICLES_DEBUG)
 #else
 #define SHADER_DEFINES ""
 #endif
+
+//TODO: Make it larger on desktop? Requires fixing up shader code with the same define
+#define UNIFORM_ARRAY_SIZE 64
+
 const float CONV = 0.017453292519943295;
 class ImageMaterialData
 {
     public:
     ImageMaterialData()
-        : texture(0), colortable(0), sizetable(0), opacitytable(0)
+        : texture(0), colorTable(0)
     {}
 
     ~ImageMaterialData(){
         delete texture;
-        delete colortable;
-        delete sizetable;
-        delete opacitytable;
+        delete colorTable;
     }
 
     QSGTexture *texture;
-    QSGTexture *colortable;
-    QSGTexture *sizetable;
-    QSGTexture *opacitytable;
+    QSGTexture *colorTable;
+    float sizeTable[UNIFORM_ARRAY_SIZE];
+    float opacityTable[UNIFORM_ARRAY_SIZE];
 
     qreal timestamp;
     qreal entry;
@@ -126,24 +128,17 @@ public:
         program()->bind();
         program()->setUniformValue("texture", 0);
         program()->setUniformValue("colortable", 1);
-        program()->setUniformValue("sizetable", 2);
-        program()->setUniformValue("opacitytable", 3);
         glFuncs = QGLContext::currentContext()->functions();
         m_timestamp_id = program()->uniformLocation("timestamp");
         m_entry_id = program()->uniformLocation("entry");
+        m_sizetable_id = program()->uniformLocation("sizetable");
+        m_opacitytable_id = program()->uniformLocation("opacitytable");
     }
 
     void updateState(const TabledMaterialData* d, const TabledMaterialData*) {
         glFuncs->glActiveTexture(GL_TEXTURE1);
-        d->colortable->bind();
-
-        glFuncs->glActiveTexture(GL_TEXTURE2);
-        d->sizetable->bind();
+        d->colorTable->bind();
 
-        glFuncs->glActiveTexture(GL_TEXTURE3);
-        d->opacitytable->bind();
-
-        // make sure we end by setting GL_TEXTURE0 as active texture
         glFuncs->glActiveTexture(GL_TEXTURE0);
         d->texture->bind();
 
@@ -151,10 +146,14 @@ public:
         program()->setUniformValue("framecount", (float) 1);
         program()->setUniformValue("animcount", (float) 1);
         program()->setUniformValue(m_entry_id, (float) d->entry);
+        program()->setUniformValueArray(m_sizetable_id, (float*) d->sizeTable, UNIFORM_ARRAY_SIZE, 1);
+        program()->setUniformValueArray(m_opacitytable_id, (float*) d->opacityTable, UNIFORM_ARRAY_SIZE, 1);
     }
 
     int m_entry_id;
     int m_timestamp_id;
+    int m_sizetable_id;
+    int m_opacitytable_id;
     QByteArray m_vertex_code;
     QByteArray m_fragment_code;
     QGLFunctions* glFuncs;
@@ -253,24 +252,18 @@ public:
         program()->bind();
         program()->setUniformValue("texture", 0);
         program()->setUniformValue("colortable", 1);
-        program()->setUniformValue("sizetable", 2);
-        program()->setUniformValue("opacitytable", 3);
         glFuncs = QGLContext::currentContext()->functions();
         m_timestamp_id = program()->uniformLocation("timestamp");
         m_framecount_id = program()->uniformLocation("framecount");
         m_animcount_id = program()->uniformLocation("animcount");
         m_entry_id = program()->uniformLocation("entry");
+        m_sizetable_id = program()->uniformLocation("sizetable");
+        m_opacitytable_id = program()->uniformLocation("sizetable");
     }
 
     void updateState(const SpriteMaterialData* d, const SpriteMaterialData*) {
         glFuncs->glActiveTexture(GL_TEXTURE1);
-        d->colortable->bind();
-
-        glFuncs->glActiveTexture(GL_TEXTURE2);
-        d->sizetable->bind();
-
-        glFuncs->glActiveTexture(GL_TEXTURE3);
-        d->opacitytable->bind();
+        d->colorTable->bind();
 
         // make sure we end by setting GL_TEXTURE0 as active texture
         glFuncs->glActiveTexture(GL_TEXTURE0);
@@ -280,12 +273,16 @@ public:
         program()->setUniformValue(m_framecount_id, (float) d->framecount);
         program()->setUniformValue(m_animcount_id, (float) d->animcount);
         program()->setUniformValue(m_entry_id, (float) d->entry);
+        program()->setUniformValueArray(m_sizetable_id, (float*) d->sizeTable, 64, 1);
+        program()->setUniformValueArray(m_opacitytable_id, (float*) d->opacityTable, UNIFORM_ARRAY_SIZE, 1);
     }
 
     int m_timestamp_id;
     int m_framecount_id;
     int m_animcount_id;
     int m_entry_id;
+    int m_sizetable_id;
+    int m_opacitytable_id;
     QByteArray m_vertex_code;
     QByteArray m_fragment_code;
     QGLFunctions* glFuncs;
@@ -431,6 +428,18 @@ public:
     QGLFunctions* glFuncs;
 };
 
+void fillUniformArrayFromImage(float* array, const QImage& img, int size)
+{
+    if (img.isNull()){
+        for (int i=0; i<size; i++)
+            array[i] = 1;
+        return;
+    }
+    QImage scaled = img.scaled(size,1);
+    for (int i=0; i<size; i++)
+        array[i] = qAlpha(scaled.pixel(i,0))/255.0;
+}
+
 /*!
     \qmlclass ImageParticle QSGImageParticle
     \inqmlmodule QtQuick.Particles 2
@@ -903,16 +912,10 @@ QSGGeometryNode* QSGImageParticle::buildParticleNodes()
         opacitytable = QImage(m_opacitytable_name.toLocalFile());
         if (colortable.isNull())
             colortable = QImage(":defaultshaders/identitytable.png");
-        if (sizetable.isNull())
-            sizetable = QImage(":defaultshaders/identitytable.png");
-        if (opacitytable.isNull())
-            opacitytable = QImage(":defaultshaders/defaultFadeInOut.png");
         Q_ASSERT(!colortable.isNull());
-        Q_ASSERT(!sizetable.isNull());
-        Q_ASSERT(!opacitytable.isNull());
-        getState<ImageMaterialData>(m_material)->colortable = sceneGraphEngine()->createTextureFromImage(colortable);
-        getState<ImageMaterialData>(m_material)->sizetable = sceneGraphEngine()->createTextureFromImage(sizetable);
-        getState<ImageMaterialData>(m_material)->opacitytable = sceneGraphEngine()->createTextureFromImage(opacitytable);
+        getState<ImageMaterialData>(m_material)->colorTable = sceneGraphEngine()->createTextureFromImage(colortable);
+        fillUniformArrayFromImage(getState<ImageMaterialData>(m_material)->sizeTable, sizetable, UNIFORM_ARRAY_SIZE);
+        fillUniformArrayFromImage(getState<ImageMaterialData>(m_material)->opacityTable, opacitytable, UNIFORM_ARRAY_SIZE);
     case Deformable:
         if (!m_material)
             m_material = DeformableMaterial::createMaterial();
index 932a308..9571648 100644 (file)
@@ -55,7 +55,7 @@ class QSGPointAttractorAffector : public QSGParticleAffector
     //Like Gravitational singularity, but linear to distance instead of quadratic
     //And affects ds/dt, not da/dt
     Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged)
-    Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
+    Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)//TODO: Change to pointX, pointY
     Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
     Q_PROPERTY(PhysicsAffects physics READ physics WRITE setPhysics NOTIFY physicsChanged)
     Q_PROPERTY(Proportion proportionalToDistance READ proportionalToDistance WRITE setProportionalToDistance NOTIFY proportionalToDistanceChanged)