aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/particles
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@nokia.com>2011-08-31 08:55:16 +0200
committerGunnar Sletta <gunnar.sletta@nokia.com>2011-08-31 08:55:16 +0200
commit71478352376022faa9be6d79f2a760c289945ff5 (patch)
tree0f8ff4a88c1b033367337a93d23a329d145ee903 /src/declarative/particles
parentc38efcb67cf93ba3e91e184c3b891efef4ef75a3 (diff)
parent05daa9bfe1a03ffe1cc580b6cfd88e093e2493c0 (diff)
Merge branch 'master' into refactor
Conflicts: src/3rdparty/v8 src/declarative/declarative.pro src/declarative/items/qsgcanvas.cpp src/declarative/items/qsgshadereffectsource_p.h src/declarative/items/qsgview.cpp src/declarative/particles/qsgcustomparticle.cpp src/imports/gestures/gestures.pro src/imports/particles/particles.pro src/plugins/qmltooling/qmldbg_inspector/qmldbg_inspector.pro src/qtquick1/qtquick1.pro tests/auto/declarative/examples/examples.pro tests/auto/declarative/qsglistview/qsglistview.pro tests/auto/qtquick1/qdeclarativeviewer/qdeclarativeviewer.pro Change-Id: I423344f83e1835116cad531b877fde6e68a8849a
Diffstat (limited to 'src/declarative/particles')
-rw-r--r--src/declarative/particles/defaultshaders/imagevertex.shader3
-rw-r--r--src/declarative/particles/qsgcustomparticle.cpp69
-rw-r--r--src/declarative/particles/qsgimageparticle.cpp4
-rw-r--r--src/declarative/particles/qsgparticleaffector.cpp10
-rw-r--r--src/declarative/particles/qsgparticlesystem_p.h1
-rw-r--r--src/declarative/particles/qsgpointattractor.cpp28
-rw-r--r--src/declarative/particles/qsgpointattractor_p.h5
-rw-r--r--src/declarative/particles/qsgv8particledata.cpp4
8 files changed, 88 insertions, 36 deletions
diff --git a/src/declarative/particles/defaultshaders/imagevertex.shader b/src/declarative/particles/defaultshaders/imagevertex.shader
index e1033c9165..9967ef85a2 100644
--- a/src/declarative/particles/defaultshaders/imagevertex.shader
+++ b/src/declarative/particles/defaultshaders/imagevertex.shader
@@ -75,8 +75,9 @@ void main() {
currentSize = currentSize * sizetable[int(floor(t*64.))];
fade = fade * opacitytable[int(floor(t*64.))];
#endif
+
if (entry == 1.)
- fade = fadeIn * fadeOut;
+ fade = fade * fadeIn * fadeOut;
else if(entry == 2.)
currentSize = currentSize * fadeIn * fadeOut;
diff --git a/src/declarative/particles/qsgcustomparticle.cpp b/src/declarative/particles/qsgcustomparticle.cpp
index db544d20e8..12d32a27b4 100644
--- a/src/declarative/particles/qsgcustomparticle.cpp
+++ b/src/declarative/particles/qsgcustomparticle.cpp
@@ -45,17 +45,17 @@
QT_BEGIN_NAMESPACE
-//TODO: Can we make the code such that you don't have to copy the whole vertex shader just to add one little calculation?
//Includes comments because the code isn't self explanatory
-static const char qt_particles_default_vertex_code[] =
+static const char qt_particles_template_vertex_code[] =
"attribute highp vec2 vPos; \n"
"attribute highp vec2 vTex; \n"
"attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize \n"
"attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration \n"
+ "attribute highp float r; \n"
"uniform highp mat4 qt_Matrix; \n"
"uniform highp float timestamp; \n"
"varying highp vec2 fTex; \n"
- "void main() { \n"
+ "void defaultMain() { \n"
" fTex = vTex; \n"
" highp float size = vData.z; \n"
" highp float endSize = vData.w; \n"
@@ -68,6 +68,10 @@ static const char qt_particles_default_vertex_code[] =
" + vVec.xy * t * vData.y // apply speed vector.. \n"
" + 0.5 * vVec.zw * pow(t * vData.y, 2.); \n"
" gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1); \n"
+ "}\n";
+static const char qt_particles_default_vertex_code[] =
+ "void main() { \n"
+ " defaultMain(); \n"
"}";
static const char qt_particles_default_fragment_code[] =//TODO: Default frag requires source?
@@ -78,9 +82,6 @@ static const char qt_particles_default_fragment_code[] =//TODO: Default frag req
" gl_FragColor = texture2D(source, fTex) * qt_Opacity; \n"
"}";
-static const char qt_position_attribute_name[] = "qt_Vertex";
-static const char qt_texcoord_attribute_name[] = "qt_MultiTexCoord0";
-
static QSGGeometry::Attribute PlainParticle_Attributes[] = {
{ 0, 2, GL_FLOAT }, // Position
{ 1, 2, GL_FLOAT }, // TexCoord
@@ -157,8 +158,9 @@ void QSGCustomParticle::componentComplete()
\qmlproperty string QtQuick.Particles2::CustomParticle::fragmentShader
This property holds the fragment shader's GLSL source code.
- The default shader passes the texture coordinate along to the fragment
- shader as "varying highp vec2 qt_TexCoord0".
+ The default shader expects the texture coordinate to be passed from the
+ vertex shader as "varying highp vec2 fTex", and it samples from a
+ sampler2D named "source".
*/
void QSGCustomParticle::setFragmentShader(const QByteArray &code)
@@ -176,9 +178,41 @@ void QSGCustomParticle::setFragmentShader(const QByteArray &code)
\qmlproperty string QtQuick.Particles2::CustomParticle::vertexShader
This property holds the vertex shader's GLSL source code.
- The default shader expects the texture coordinate to be passed from the
- vertex shader as "varying highp vec2 qt_TexCoord0", and it samples from a
- sampler2D named "source".
+
+ The default shader passes the texture coordinate along to the fragment
+ shader as "varying highp vec2 fTex".
+
+ To aid writing a particle vertex shader, the following GLSL code is prepended
+ to your vertex shader:
+ \code
+ attribute highp vec2 vPos;
+ attribute highp vec2 vTex;
+ attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
+ attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration
+ attribute highp float r;
+ uniform highp mat4 qt_Matrix;
+ uniform highp float timestamp;
+ varying highp vec2 fTex;
+ void defaultMain() {
+ fTex = vTex;
+ highp float size = vData.z;
+ highp float endSize = vData.w;
+ highp float t = (timestamp - vData.x) / vData.y;
+ highp float currentSize = mix(size, endSize, t * t);
+ if (t < 0. || t > 1.)
+ currentSize = 0.;
+ highp vec2 pos = vPos
+ - currentSize / 2. + currentSize * vTex // adjust size
+ + vVec.xy * t * vData.y // apply speed vector..
+ + 0.5 * vVec.zw * pow(t * vData.y, 2.);
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
+ }
+ \endcode
+
+ defaultMain() is the same code as in the default shader, you can call this for basic
+ particle functions and then add additional variables for custom effects. Note that
+ the vertex shader for particles is responsible for simulating the movement of particles
+ over time, the particle data itself only has the starting position and spawn time.
*/
void QSGCustomParticle::setVertexShader(const QByteArray &code)
@@ -311,6 +345,7 @@ void QSGCustomParticle::updateProperties()
vertexCode = qt_particles_default_vertex_code;
if (fragmentCode.isEmpty())
fragmentCode = qt_particles_default_fragment_code;
+ vertexCode = qt_particles_template_vertex_code + vertexCode;
m_source.attributeNames.clear();
m_source.attributeNames << "vPos" << "vTex" << "vData" << "vVec" << "r";
@@ -318,10 +353,6 @@ void QSGCustomParticle::updateProperties()
lookThroughShaderCode(vertexCode);
lookThroughShaderCode(fragmentCode);
- if (!m_source.attributeNames.contains(qt_position_attribute_name))
- qWarning("QSGCustomParticle: Missing reference to \'%s\'.", qt_position_attribute_name);
- if (!m_source.attributeNames.contains(qt_texcoord_attribute_name))
- qWarning("QSGCustomParticle: Missing reference to \'%s\'.", qt_texcoord_attribute_name);
if (!m_source.respectsMatrix)
qWarning("QSGCustomParticle: Missing reference to \'qt_Matrix\'.");
if (!m_source.respectsOpacity)
@@ -352,17 +383,13 @@ void QSGCustomParticle::lookThroughShaderCode(const QByteArray &code)
QByteArray name = re.cap(3).toLatin1(); // variable name
if (decl == "attribute") {
- if (!m_source.attributeNames.contains(name))//TODO: Can they add custom attributes?
+ if (!m_source.attributeNames.contains(name))
qWarning() << "Custom Particle: Unknown attribute " << name;
} else {
Q_ASSERT(decl == "uniform");//TODO: Shouldn't assert
if (name == "qt_Matrix") {
m_source.respectsMatrix = true;
- } else if (name == "qt_ModelViewProjectionMatrix") {
- // TODO: Remove after grace period.
- qWarning("ShaderEffect: qt_ModelViewProjectionMatrix is deprecated. Use qt_Matrix instead.");
- m_source.respectsMatrix = true;
} else if (name == "qt_Opacity") {
m_source.respectsOpacity = true;
} else if (name == "timestamp") {
@@ -443,7 +470,9 @@ QSGShaderEffectNode* QSGCustomParticle::buildCustomNodes()
m_material = new QSGShaderEffectMaterialObject;
}
+ s.vertexCode = qt_particles_template_vertex_code + s.vertexCode;
m_material->setProgramSource(s);
+
foreach (const QString &str, m_particles){
int gIdx = m_system->m_groupIds[str];
int count = m_system->m_groupData[gIdx]->size();
diff --git a/src/declarative/particles/qsgimageparticle.cpp b/src/declarative/particles/qsgimageparticle.cpp
index 737b393de7..853a08a890 100644
--- a/src/declarative/particles/qsgimageparticle.cpp
+++ b/src/declarative/particles/qsgimageparticle.cpp
@@ -258,7 +258,7 @@ public:
m_animcount_id = program()->uniformLocation("animcount");
m_entry_id = program()->uniformLocation("entry");
m_sizetable_id = program()->uniformLocation("sizetable");
- m_opacitytable_id = program()->uniformLocation("sizetable");
+ m_opacitytable_id = program()->uniformLocation("opacitytable");
}
void updateState(const SpriteMaterialData* d, const SpriteMaterialData*) {
@@ -432,7 +432,7 @@ void fillUniformArrayFromImage(float* array, const QImage& img, int size)
{
if (img.isNull()){
for (int i=0; i<size; i++)
- array[i] = 1;
+ array[i] = 1.0;
return;
}
QImage scaled = img.scaled(size,1);
diff --git a/src/declarative/particles/qsgparticleaffector.cpp b/src/declarative/particles/qsgparticleaffector.cpp
index 4cb3e49403..331310625f 100644
--- a/src/declarative/particles/qsgparticleaffector.cpp
+++ b/src/declarative/particles/qsgparticleaffector.cpp
@@ -42,6 +42,7 @@
#include "qsgparticleaffector_p.h"
#include <QDebug>
QT_BEGIN_NAMESPACE
+
/*!
\qmlclass Affector QSGParticleAffector
\inqmlmodule QtQuick.Particles 2
@@ -159,8 +160,10 @@ void QSGParticleAffector::affectSystem(qreal dt)
if ((m_onceOff && m_onceOffed.contains(qMakePair(d->group, d->index)))
|| !d->stillAlive())
continue;
- //Need to have previous location for affected. if signal || shape might be faster?
- QPointF curPos = QPointF(d->curX(), d->curY());
+ //Need to have previous location for affected anyways
+ QPointF curPos;
+ if (m_signal || (width() && height()))
+ curPos = QPointF(d->curX(), d->curY());
if (width() == 0 || height() == 0
|| m_shape->contains(QRectF(m_offset.x(), m_offset.y(), width(), height()),curPos)){
if (m_collisionParticles.isEmpty() || isColliding(d)){
@@ -181,8 +184,9 @@ void QSGParticleAffector::affectSystem(qreal dt)
bool QSGParticleAffector::affectParticle(QSGParticleData *d, qreal dt)
{
if (isAffectConnected()){
+ d->update = 0.0;
emit affectParticle(d->v8Value(), dt);
- return true;
+ return d->update == 1.0;
}
return m_signal;//If signalling, then we always 'null affect' it.
}
diff --git a/src/declarative/particles/qsgparticlesystem_p.h b/src/declarative/particles/qsgparticlesystem_p.h
index 9f4020d041..abb7f52c31 100644
--- a/src/declarative/particles/qsgparticlesystem_p.h
+++ b/src/declarative/particles/qsgparticlesystem_p.h
@@ -202,6 +202,7 @@ public:
float r;
QSGItem* delegate;
int modelIndex;
+ float update;//Used by custom affectors
void debugDump();
bool stillAlive();
diff --git a/src/declarative/particles/qsgpointattractor.cpp b/src/declarative/particles/qsgpointattractor.cpp
index 1a3c3c25c5..21eaeaac12 100644
--- a/src/declarative/particles/qsgpointattractor.cpp
+++ b/src/declarative/particles/qsgpointattractor.cpp
@@ -65,21 +65,31 @@ bool QSGPointAttractorAffector::affectParticle(QSGParticleData *d, qreal dt)
{
if (m_strength == 0.0)
return false;
- qreal dx = m_y - d->curX();
- qreal dy = m_x - d->curY();
+ qreal dx = m_x - d->curX();
+ qreal dy = m_y - d->curY();
qreal r = sqrt((dx*dx) + (dy*dy));
qreal theta = atan2(dy,dx);
qreal ds = 0;
switch (m_proportionalToDistance){
+ case InverseQuadratic:
+ ds = (m_strength / qMax<qreal>(1.,r*r));
+ break;
+ case InverseLinear:
+ ds = (m_strength / qMax<qreal>(1.,r));
+ break;
case Quadratic:
- ds = (m_strength / qMax<qreal>(1.,r*r)) * dt;
+ ds = (m_strength * qMax<qreal>(1.,r*r));
break;
- case Linear://also default
- default:
- ds = (m_strength / qMax<qreal>(1.,r)) * dt;
+ case Linear:
+ ds = (m_strength * qMax<qreal>(1.,r));
+ break;
+ default: //also Constant
+ ds = m_strength;
}
+ ds *= dt;
dx = ds * cos(theta);
dy = ds * sin(theta);
+ qreal vx,vy;
switch (m_physics){
case Position:
d->x = (d->x + dx);
@@ -91,8 +101,10 @@ bool QSGPointAttractorAffector::affectParticle(QSGParticleData *d, qreal dt)
break;
case Velocity: //also default
default:
- d->setInstantaneousVX(d->vx + dx);
- d->setInstantaneousVY(d->vy + dy);
+ vx = d->curVX();
+ vy = d->curVY();
+ d->setInstantaneousVX(vx + dx);
+ d->setInstantaneousVY(vy + dy);
}
return true;
diff --git a/src/declarative/particles/qsgpointattractor_p.h b/src/declarative/particles/qsgpointattractor_p.h
index 95716483ed..298965a5c9 100644
--- a/src/declarative/particles/qsgpointattractor_p.h
+++ b/src/declarative/particles/qsgpointattractor_p.h
@@ -64,8 +64,11 @@ class QSGPointAttractorAffector : public QSGParticleAffector
public:
enum Proportion{
+ Constant,
Linear,
- Quadratic
+ Quadratic,
+ InverseLinear,
+ InverseQuadratic
};
enum PhysicsAffects {
diff --git a/src/declarative/particles/qsgv8particledata.cpp b/src/declarative/particles/qsgv8particledata.cpp
index b3ff482d8b..72c0b7c2de 100644
--- a/src/declarative/particles/qsgv8particledata.cpp
+++ b/src/declarative/particles/qsgv8particledata.cpp
@@ -150,6 +150,7 @@ FLOAT_GETTER_AND_SETTER(frameDuration)
FLOAT_GETTER_AND_SETTER(frameCount)
FLOAT_GETTER_AND_SETTER(animT)
FLOAT_GETTER_AND_SETTER(r)
+FLOAT_GETTER_AND_SETTER(update)
FAKE_FLOAT_GETTER_AND_SETTER(curX, curX, setInstantaneousX)
FAKE_FLOAT_GETTER_AND_SETTER(curVX, curVX, setInstantaneousVX)
FAKE_FLOAT_GETTER_AND_SETTER(curAX, curAX, setInstantaneousAX)
@@ -157,7 +158,7 @@ FAKE_FLOAT_GETTER_AND_SETTER(curY, curY, setInstantaneousY)
FAKE_FLOAT_GETTER_AND_SETTER(curVY, curVY, setInstantaneousVY)
FAKE_FLOAT_GETTER_AND_SETTER(curAY, curAY, setInstantaneousAY)
-//TODO: Non-floats (color) and special floats (curX) once basic floats are working well
+//TODO: Non-floats (color, update?) once floats are working well
QV8ParticleDataDeletable::QV8ParticleDataDeletable(QV8Engine *engine)
{
@@ -189,6 +190,7 @@ QV8ParticleDataDeletable::QV8ParticleDataDeletable(QV8Engine *engine)
FLOAT_REGISTER_ACCESSOR(ft, engine, frameCount);
FLOAT_REGISTER_ACCESSOR(ft, engine, animT);
FLOAT_REGISTER_ACCESSOR(ft, engine, r);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, update);
FLOAT_REGISTER_ACCESSOR(ft, engine, curX);
FLOAT_REGISTER_ACCESSOR(ft, engine, curVX);
FLOAT_REGISTER_ACCESSOR(ft, engine, curAX);