From: Alan Alpert Date: Tue, 30 Aug 2011 04:35:09 +0000 (+1000) Subject: Custom Particle now supplies default code X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=5cc0a29582fc69e9b748fd697a9a2dec3e64148c;p=konrad%2Fqtdeclarative.git Custom Particle now supplies default code Attributes and a sample function are now prepended to the vertex shader, allowing many to become simple again. Change-Id: Ie1fbc864bd0d58647cb67994b96c2cb88db92f10 Reviewed-on: http://codereview.qt.nokia.com/3839 Reviewed-by: Qt Sanity Bot Reviewed-by: Glenn Watson Reviewed-by: Alan Alpert --- diff --git a/examples/declarative/particles/allsmiles/smile.qml b/examples/declarative/particles/allsmiles/smile.qml index 3eb5761..bfce60c 100644 --- a/examples/declarative/particles/allsmiles/smile.qml +++ b/examples/declarative/particles/allsmiles/smile.qml @@ -70,47 +70,17 @@ Rectangle{ source: "content/particle.png" } vertexShader:" - 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 float maxWidth; uniform highp float maxHeight; - - uniform highp mat4 qt_Matrix; - uniform highp float timestamp; - uniform lowp float qt_Opacity; - - varying highp vec2 fTex; - varying highp vec2 fTex2; + varying highp vec2 fTex2; varying lowp float fFade; + uniform lowp float qt_Opacity; void main() { - fTex = vTex; fTex2 = vec2(vPos.x / maxWidth, vPos.y / maxHeight); - 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); - - highp float fadeIn = min(t * 10., 1.); - highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.)); - - fFade = fadeIn * fadeOut * qt_Opacity; + fFade = min(t*4., (1.-t*t)*.75) * qt_Opacity; + defaultMain(); } " property variant particleTexture: particleSource @@ -120,7 +90,7 @@ Rectangle{ uniform sampler2D pictureTexture; varying highp vec2 fTex; varying highp vec2 fTex2; - varying highp float fFade; + varying lowp float fFade; void main() { gl_FragColor = texture2D(pictureTexture, fTex2) * texture2D(particleTexture, fTex).w * fFade; }" diff --git a/examples/declarative/particles/custom/blurparticles.qml b/examples/declarative/particles/custom/blurparticles.qml index 7974c6a..238608c 100644 --- a/examples/declarative/particles/custom/blurparticles.qml +++ b/examples/declarative/particles/custom/blurparticles.qml @@ -68,41 +68,14 @@ Rectangle{ CustomParticle{ system: sys - //TODO: Someway that you don't have to rewrite the basics for a simple addition vertexShader:" - 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; uniform lowp float qt_Opacity; - - varying highp vec2 fTex; varying lowp float fFade; varying lowp float fBlur; void main() { - fTex = vTex; - highp float size = vData.z; - highp float endSize = vData.w; - + defaultMain(); 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); - highp float fadeIn = min(t * 10., 1.); highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.)); diff --git a/examples/declarative/particles/custom/custom.qml b/examples/declarative/particles/custom/custom.qml index 9a562af..4b75cf6 100644 --- a/examples/declarative/particles/custom/custom.qml +++ b/examples/declarative/particles/custom/custom.qml @@ -44,18 +44,8 @@ ParticleSystem{ } } CustomParticle{ - //TODO: Someway that you don't have to rewrite the basics for a simple addition vertexShader:" - 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 - - uniform highp mat4 qt_ModelViewProjectionMatrix; - uniform highp float timestamp; uniform lowp float qt_Opacity; - - varying highp vec2 fTex; varying lowp float fFade; varying highp vec2 fPos; @@ -76,7 +66,7 @@ ParticleSystem{ + vVec.xy * t * vData.y // apply speed vector.. + 0.5 * vVec.zw * pow(t * vData.y, 2.); - gl_Position = qt_ModelViewProjectionMatrix * vec4(pos.x, pos.y, 0, 1); + gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1); highp float fadeIn = min(t * 20., 1.); highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.)); diff --git a/examples/declarative/particles/custom/shader.qml b/examples/declarative/particles/custom/shader.qml index 329eaf2..6253679 100644 --- a/examples/declarative/particles/custom/shader.qml +++ b/examples/declarative/particles/custom/shader.qml @@ -27,19 +27,8 @@ ParticleSystem{ acceleration: PointDirection{x: -root.width/40; y: -root.height/40; xVariation: -root.width/20; yVariation: -root.width/20} } CustomParticle{ - //TODO: Someway that you don't have to rewrite the basics for a simple addition vertexShader:" - 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; uniform lowp float qt_Opacity; - - varying highp vec2 fTex; varying lowp float fFade; varying highp vec2 fPos; diff --git a/src/declarative/particles/qsgcustomparticle.cpp b/src/declarative/particles/qsgcustomparticle.cpp index 2d86306..11bc7e3 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 @@ -148,8 +149,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) @@ -167,9 +169,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) @@ -303,6 +337,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"; @@ -310,10 +345,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) @@ -344,17 +375,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") { @@ -430,6 +457,7 @@ QSGShaderEffectNode* QSGCustomParticle::buildCustomNodes() s.fragmentCode = qt_particles_default_fragment_code; if (s.vertexCode.isEmpty()) s.vertexCode = qt_particles_default_vertex_code; + 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];