From: Alan Alpert Date: Thu, 18 Aug 2011 10:47:23 +0000 (+1000) Subject: Add the rest of the tiered shaders to QSGImageParticle X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=4ce1af458c67d824fd2412c1a2f847af39b04902;p=konrad%2Fqtdeclarative.git Add the rest of the tiered shaders to QSGImageParticle Also simplifies the use of multiple shaders. Change-Id: Ib4e16406865407626e4e736e7daeba4855dc0574 Reviewed-on: http://codereview.qt.nokia.com/3174 Reviewed-by: Alan Alpert --- diff --git a/src/declarative/particles/defaultshaders/coloredfragment.shader b/src/declarative/particles/defaultshaders/coloredfragment.shader new file mode 100644 index 0000000..383888b --- /dev/null +++ b/src/declarative/particles/defaultshaders/coloredfragment.shader @@ -0,0 +1,10 @@ +uniform sampler2D texture; +uniform lowp float qt_Opacity; + +varying highp vec2 fTex; +varying lowp vec4 fColor; + +void main() { + gl_FragColor = (texture2D(texture, fTex)) * fColor * qt_Opacity; +} + diff --git a/src/declarative/particles/defaultshaders/trailsvertex.shader b/src/declarative/particles/defaultshaders/coloredvertex.shader similarity index 71% rename from src/declarative/particles/defaultshaders/trailsvertex.shader rename to src/declarative/particles/defaultshaders/coloredvertex.shader index 7bc1d66..d6498f2 100644 --- a/src/declarative/particles/defaultshaders/trailsvertex.shader +++ b/src/declarative/particles/defaultshaders/coloredvertex.shader @@ -4,15 +4,14 @@ attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration attribute lowp vec4 vColor; -uniform highp mat4 matrix; +uniform highp mat4 qt_Matrix; uniform highp float timestamp; -uniform lowp float opacity; -varying highp vec2 fTex; +varying highp vec2 fTex; varying lowp vec4 fColor; -void main() { - fTex = vTex; +void main() { + fTex = vTex; highp float size = vData.z; highp float endSize = vData.w; @@ -28,10 +27,10 @@ void main() { + vVec.xy * t * vData.y // apply speed vector.. + 0.5 * vVec.zw * pow(t * vData.y, 2.); - gl_Position = matrix * vec4(pos.x, pos.y, 0, 1); + 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.)); - fColor = vColor * fadeIn * fadeOut * opacity; + fColor = vColor * (fadeIn * fadeOut); } diff --git a/src/declarative/particles/defaultshaders/ctfragment.shader b/src/declarative/particles/defaultshaders/ctfragment.shader deleted file mode 100644 index a17f584..0000000 --- a/src/declarative/particles/defaultshaders/ctfragment.shader +++ /dev/null @@ -1,11 +0,0 @@ -uniform sampler2D texture; -uniform sampler2D colortable; -uniform sampler2D opacitytable; - -varying highp vec2 fTex; -varying lowp vec4 fColor; -varying lowp float tt; - -void main() { - gl_FragColor = (texture2D(texture, fTex).w) * fColor * texture2D(colortable, vec2(tt, 0.5)) *( texture2D(opacitytable, vec2(tt, 0.5)).w); -} diff --git a/src/declarative/particles/defaultshaders/ctvertex.shader b/src/declarative/particles/defaultshaders/ctvertex.shader deleted file mode 100644 index b20676c..0000000 --- a/src/declarative/particles/defaultshaders/ctvertex.shader +++ /dev/null @@ -1,38 +0,0 @@ -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 lowp vec4 vColor; - -uniform highp mat4 matrix; -uniform highp float timestamp; -uniform sampler2D sizetable; -uniform sampler2D opacitytable; - -varying highp vec2 fTex; -varying lowp vec4 fColor; -varying lowp float tt; - -void main() { - 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) * texture2D(sizetable, vec2(t,0.5)).w; - - 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 = matrix * vec4(pos.x, pos.y, 0, 1); - - fColor = vColor; - tt = t; - -} diff --git a/src/declarative/particles/defaultshaders/deformablefragment.shader b/src/declarative/particles/defaultshaders/deformablefragment.shader index 494053e..1ac25ba 100644 --- a/src/declarative/particles/defaultshaders/deformablefragment.shader +++ b/src/declarative/particles/defaultshaders/deformablefragment.shader @@ -1,8 +1,9 @@ uniform sampler2D texture; +uniform lowp float qt_Opacity; varying highp vec2 fTex; -varying lowp float fFade; +varying lowp vec4 fColor; void main() { - gl_FragColor = (texture2D(texture, fTex)) * fFade; + gl_FragColor = (texture2D(texture, fTex)) * fColor * qt_Opacity; } diff --git a/src/declarative/particles/defaultshaders/deformablevertex.shader b/src/declarative/particles/defaultshaders/deformablevertex.shader index 0157095..0019984 100644 --- a/src/declarative/particles/defaultshaders/deformablevertex.shader +++ b/src/declarative/particles/defaultshaders/deformablevertex.shader @@ -4,13 +4,13 @@ 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 vec4 vDeformVec; //x,y x unit vector; z,w = y unit vector attribute highp vec3 vRotation; //x = radians of rotation, y=rotation speed, z= bool autoRotate +attribute lowp vec4 vColor; -uniform highp mat4 matrix; +uniform highp mat4 qt_Matrix; uniform highp float timestamp; -uniform lowp float opacity; varying highp vec2 fTex; -varying lowp float fFade; +varying lowp vec4 fColor; void main() { fTex = vTex; @@ -21,37 +21,35 @@ void main() { highp float currentSize = mix(size, endSize, t * t); - highp vec2 pos; - if (t < 0. || t > 1.){ + if (t < 0. || t > 1.) currentSize = 0.; - pos = vPos; - }else{ - 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; - rotation += atan(curVel.y, curVel.x); - } - highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation)); - 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 = vPos - + xRotatedDeform - + yRotatedDeform - //- vec2(1,1) * currentSize * 0.5 // 'center' - + vVec.xy * t * vData.y // apply speed - + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration - } - gl_Position = matrix * vec4(pos.x, pos.y, 0, 1); + highp vec2 pos; + 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; + rotation += atan(curVel.y, curVel.x); + } + highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation)); + 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 = vPos + + xRotatedDeform + + yRotatedDeform + //- vec2(1,1) * currentSize * 0.5 // 'center' + + vVec.xy * t * vData.y // apply speed + + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration + + 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 * opacity; + fColor = vColor * (fadeIn * fadeOut); } diff --git a/src/declarative/particles/defaultshaders/simplefragment.shader b/src/declarative/particles/defaultshaders/simplefragment.shader index 494053e..0b0adaa 100644 --- a/src/declarative/particles/defaultshaders/simplefragment.shader +++ b/src/declarative/particles/defaultshaders/simplefragment.shader @@ -1,8 +1,9 @@ uniform sampler2D texture; +uniform lowp float qt_Opacity; varying highp vec2 fTex; varying lowp float fFade; void main() { - gl_FragColor = (texture2D(texture, fTex)) * fFade; + gl_FragColor = texture2D(texture, fTex) * (fFade * qt_Opacity); } diff --git a/src/declarative/particles/defaultshaders/simplevertex.shader b/src/declarative/particles/defaultshaders/simplevertex.shader index f185ef0..b7542e6 100644 --- a/src/declarative/particles/defaultshaders/simplevertex.shader +++ b/src/declarative/particles/defaultshaders/simplevertex.shader @@ -3,9 +3,8 @@ 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 matrix; +uniform highp mat4 qt_Matrix; uniform highp float timestamp; -uniform lowp float opacity; varying highp vec2 fTex; varying lowp float fFade; @@ -27,10 +26,10 @@ void main() { + vVec.xy * t * vData.y // apply speed vector.. + 0.5 * vVec.zw * pow(t * vData.y, 2.); - gl_Position = matrix * vec4(pos.x, pos.y, 0, 1); + 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 * opacity; + fFade = fadeIn * fadeOut; } diff --git a/src/declarative/particles/defaultshaders/spritefragment.shader b/src/declarative/particles/defaultshaders/spritefragment.shader index 4d89d69..86002f0 100644 --- a/src/declarative/particles/defaultshaders/spritefragment.shader +++ b/src/declarative/particles/defaultshaders/spritefragment.shader @@ -1,10 +1,17 @@ uniform sampler2D texture; +uniform sampler2D colortable; +uniform sampler2D opacitytable; +uniform lowp float qt_Opacity; varying highp vec2 fTexA; varying highp vec2 fTexB; varying lowp float progress; varying lowp vec4 fColor; +varying lowp float tt; void main() { - gl_FragColor = mix(texture2D(texture, fTexA), texture2D(texture, fTexB), progress) * fColor.w; + gl_FragColor = mix(texture2D(texture, fTexA), texture2D(texture, fTexB), progress) + * fColor + * texture2D(colortable, vec2(tt, 0.5)) + * (texture2D(opacitytable, vec2(tt, 0.5)).w * qt_Opacity); } diff --git a/src/declarative/particles/defaultshaders/spritevertex.shader b/src/declarative/particles/defaultshaders/spritevertex.shader index 78b8e36..7d89726 100644 --- a/src/declarative/particles/defaultshaders/spritevertex.shader +++ b/src/declarative/particles/defaultshaders/spritevertex.shader @@ -1,21 +1,25 @@ attribute highp vec2 vPos; -attribute highp vec2 vTex; +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 lowp vec4 vColor; +attribute highp vec4 vDeformVec; //x,y x unit vector; z,w = y unit vector +attribute highp vec3 vRotation; //x = radians of rotation, y=rotation speed, z= bool autoRotate attribute highp vec4 vAnimData;// idx, duration, frameCount (this anim), timestamp (this anim) -uniform highp mat4 matrix; -uniform highp float timestamp; -uniform lowp float opacity; +uniform highp mat4 qt_Matrix; +uniform highp float timestamp; uniform highp float framecount; //maximum of all anims uniform highp float animcount; +varying lowp float tt; varying highp vec2 fTexA; varying highp vec2 fTexB; varying lowp float progress; varying lowp vec4 fColor; -void main() { + +void main() { highp float size = vData.z; highp float endSize = vData.w; @@ -54,24 +58,36 @@ void main() { frameTex.y = 1. * ((vAnimData.x + 1.)/animcount); fTexB = frameTex; - //Applying Size here seems to screw with RockingAffector? highp float currentSize = mix(size, endSize, t * t); if (t < 0. || t > 1.) currentSize = 0.; - //If affector is mananging pos, they don't set speed? - 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 = matrix * vec4(pos.x, pos.y, 0, 1); - - // calculate opacity - highp float fadeIn = min(t * 10., 1.); - highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.)); + highp vec2 pos; + 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; + rotation += atan(curVel.y, curVel.x); + } + highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation)); + 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 = vPos + + xRotatedDeform + + yRotatedDeform + //- vec2(1,1) * currentSize * 0.5 // 'center' + + vVec.xy * t * vData.y // apply speed + + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration + + gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1); + + fColor = vColor; + tt = t; - lowp vec4 white = vec4(1.); - fColor = white * fadeIn * fadeOut * opacity; } diff --git a/src/declarative/particles/defaultshaders/superfragment.shader b/src/declarative/particles/defaultshaders/superfragment.shader deleted file mode 100644 index a17f584..0000000 --- a/src/declarative/particles/defaultshaders/superfragment.shader +++ /dev/null @@ -1,11 +0,0 @@ -uniform sampler2D texture; -uniform sampler2D colortable; -uniform sampler2D opacitytable; - -varying highp vec2 fTex; -varying lowp vec4 fColor; -varying lowp float tt; - -void main() { - gl_FragColor = (texture2D(texture, fTex).w) * fColor * texture2D(colortable, vec2(tt, 0.5)) *( texture2D(opacitytable, vec2(tt, 0.5)).w); -} diff --git a/src/declarative/particles/defaultshaders/supervertex.shader b/src/declarative/particles/defaultshaders/supervertex.shader deleted file mode 100644 index 432a23c..0000000 --- a/src/declarative/particles/defaultshaders/supervertex.shader +++ /dev/null @@ -1,57 +0,0 @@ -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 lowp vec4 vColor; -attribute highp vec4 vDeformVec; //x,y x unit vector; z,w = y unit vector -attribute highp vec3 vRotation; //x = radians of rotation, y=rotation speed, z= bool autoRotate - -uniform highp mat4 matrix; -uniform highp float timestamp; -uniform sampler2D sizetable; -uniform sampler2D opacitytable; - -varying highp vec2 fTex; -varying lowp vec4 fColor; -varying lowp float tt; - -void main() { - 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) * texture2D(sizetable, vec2(t,0.5)).w; - - if (t < 0. || t > 1.) - currentSize = 0.; - - highp vec2 pos; - 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; - rotation += atan(curVel.y, curVel.x); - } - highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation)); - 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 = vPos - + xRotatedDeform - + yRotatedDeform - //- vec2(1,1) * currentSize * 0.5 // 'center' - + vVec.xy * t * vData.y // apply speed - + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration - - gl_Position = matrix * vec4(pos.x, pos.y, 0, 1); - - fColor = vColor; - tt = t; - -} diff --git a/src/declarative/particles/defaultshaders/tabledvertex.shader b/src/declarative/particles/defaultshaders/tabledvertex.shader index d09abbd..ef3c35d 100644 --- a/src/declarative/particles/defaultshaders/tabledvertex.shader +++ b/src/declarative/particles/defaultshaders/tabledvertex.shader @@ -5,7 +5,6 @@ attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration attribute lowp vec4 vColor; attribute highp vec4 vDeformVec; //x,y x unit vector; z,w = y unit vector attribute highp vec3 vRotation; //x = radians of rotation, y=rotation speed, z= bool autoRotate -attribute highp vec4 vAnimData;// idx, duration, frameCount (this anim), timestamp (this anim) uniform highp mat4 qt_Matrix; uniform highp float timestamp; @@ -17,12 +16,12 @@ varying lowp vec4 fColor; void main() { + fTex = vTex; highp float size = vData.z; highp float endSize = vData.w; highp float t = (timestamp - vData.x) / vData.y; - fTex = vTex; highp float currentSize = mix(size, endSize, t * t); if (t < 0. || t > 1.) currentSize = 0.; diff --git a/src/declarative/particles/defaultshaders/trailsfragment.shader b/src/declarative/particles/defaultshaders/trailsfragment.shader deleted file mode 100644 index d3db87f..0000000 --- a/src/declarative/particles/defaultshaders/trailsfragment.shader +++ /dev/null @@ -1,8 +0,0 @@ -uniform sampler2D texture; - -varying highp vec2 fTex; -varying lowp vec4 fColor; - -void main() { - gl_FragColor = (texture2D(texture, fTex).w) * fColor; -} diff --git a/src/declarative/particles/defaultshaders/ultrafragment.shader b/src/declarative/particles/defaultshaders/ultrafragment.shader deleted file mode 100644 index 0627d0f..0000000 --- a/src/declarative/particles/defaultshaders/ultrafragment.shader +++ /dev/null @@ -1,16 +0,0 @@ -uniform sampler2D texture; -uniform sampler2D colortable; -uniform sampler2D opacitytable; - -varying highp vec2 fTexA; -varying highp vec2 fTexB; -varying lowp float progress; -varying lowp vec4 fColor; -varying lowp float tt; - -void main() { - gl_FragColor = mix(texture2D(texture, fTexA), texture2D(texture, fTexB), progress) - * fColor - * texture2D(colortable, vec2(tt, 0.5)) - *( texture2D(opacitytable, vec2(tt, 0.5)).w); -} diff --git a/src/declarative/particles/defaultshaders/ultravertex.shader b/src/declarative/particles/defaultshaders/ultravertex.shader deleted file mode 100644 index 65a1a30..0000000 --- a/src/declarative/particles/defaultshaders/ultravertex.shader +++ /dev/null @@ -1,94 +0,0 @@ -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 lowp vec4 vColor; -attribute highp vec4 vDeformVec; //x,y x unit vector; z,w = y unit vector -attribute highp vec3 vRotation; //x = radians of rotation, y=rotation speed, z= bool autoRotate -attribute highp vec4 vAnimData;// idx, duration, frameCount (this anim), timestamp (this anim) - -uniform highp mat4 matrix; -uniform highp float timestamp; -uniform highp float framecount; //maximum of all anims -uniform highp float animcount; -uniform sampler2D sizetable; - -varying lowp float tt; -varying highp vec2 fTexA; -varying highp vec2 fTexB; -varying lowp float progress; -varying lowp vec4 fColor; - - -void main() { - highp float size = vData.z; - highp float endSize = vData.w; - - highp float t = (timestamp - vData.x) / vData.y; - - //Calculate frame location in texture - highp float frameIndex = mod((((timestamp - vAnimData.w)*1000.)/vAnimData.y),vAnimData.z); - progress = mod((timestamp - vAnimData.w)*1000., vAnimData.y) / vAnimData.y; - - frameIndex = floor(frameIndex); - highp vec2 frameTex = vTex; - if(vTex.x == 0.) - frameTex.x = (frameIndex/framecount); - else - frameTex.x = 1. * ((frameIndex + 1.)/framecount); - - if(vTex.y == 0.) - frameTex.y = (vAnimData.x/animcount); - else - frameTex.y = 1. * ((vAnimData.x + 1.)/animcount); - - fTexA = frameTex; - //Next frame is also passed, for interpolation - //### Should the next anim be precalculated to allow for interpolation there? - if(frameIndex != vAnimData.z - 1.)//Can't do it for the last frame though, this anim may not loop - frameIndex = mod(frameIndex+1., vAnimData.z); - - if(vTex.x == 0.) - frameTex.x = (frameIndex/framecount); - else - frameTex.x = 1. * ((frameIndex + 1.)/framecount); - - if(vTex.y == 0.) - frameTex.y = (vAnimData.x/animcount); - else - frameTex.y = 1. * ((vAnimData.x + 1.)/animcount); - fTexB = frameTex; - - highp float currentSize = mix(size, endSize, t * t) * texture2D(sizetable, vec2(t,0.5)).w; - - if (t < 0. || t > 1.) - currentSize = 0.; - - highp vec2 pos; - 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; - rotation += atan(curVel.y, curVel.x); - } - highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation)); - 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 = vPos - + xRotatedDeform - + yRotatedDeform - //- vec2(1,1) * currentSize * 0.5 // 'center' - + vVec.xy * t * vData.y // apply speed - + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration - - gl_Position = matrix * vec4(pos.x, pos.y, 0, 1); - - fColor = vColor; - tt = t; - -} diff --git a/src/declarative/particles/particles.qrc b/src/declarative/particles/particles.qrc index 0f2325f..b9dc322 100644 --- a/src/declarative/particles/particles.qrc +++ b/src/declarative/particles/particles.qrc @@ -1,18 +1,18 @@ - defaultshaders/spritefragment.shader - defaultshaders/spritevertex.shader defaultshaders/spriteimagefragment.shader defaultshaders/spriteimagevertex.shader - defaultshaders/identitytable.png - defaultshaders/defaultFadeInOut.png + defaultshaders/tabledvertex.shader + defaultshaders/tabledfragment.shader + defaultshaders/spritefragment.shader + defaultshaders/spritevertex.shader defaultshaders/deformablefragment.shader defaultshaders/deformablevertex.shader - defaultshaders/ultravertex.shader - defaultshaders/ultrafragment.shader + defaultshaders/coloredvertex.shader + defaultshaders/coloredfragment.shader defaultshaders/simplevertex.shader defaultshaders/simplefragment.shader - defaultshaders/tabledvertex.shader - defaultshaders/tabledfragment.shader + defaultshaders/identitytable.png + defaultshaders/defaultFadeInOut.png diff --git a/src/declarative/particles/qsgimageparticle.cpp b/src/declarative/particles/qsgimageparticle.cpp index 43e44e2..08d78af 100644 --- a/src/declarative/particles/qsgimageparticle.cpp +++ b/src/declarative/particles/qsgimageparticle.cpp @@ -58,14 +58,14 @@ QT_BEGIN_NAMESPACE DEFINE_BOOL_CONFIG_OPTION(qmlParticlesDebug, QML_PARTICLES_DEBUG) const float CONV = 0.017453292519943295; -class TabledMaterialData +class ImageMaterialData { public: - TabledMaterialData() + ImageMaterialData() : texture(0), colortable(0), sizetable(0), opacitytable(0) {} - ~TabledMaterialData(){ + ~ImageMaterialData(){ delete texture; delete colortable; delete sizetable; @@ -78,8 +78,12 @@ class TabledMaterialData QSGTexture *opacitytable; qreal timestamp; + qreal framecount; + qreal animcount; }; +//TODO: Move shaders inline once they've stablilized +class TabledMaterialData : public ImageMaterialData {}; class TabledMaterial : public QSGSimpleMaterialShader { QSG_DECLARE_SIMPLE_SHADER(TabledMaterial, TabledMaterialData) @@ -104,7 +108,7 @@ public: QList attributes() const { return QList() << "vPos" << "vTex" << "vData" << "vVec" - << "vColor" << "vDeformVec" << "vRotation" << "vAnimData"; + << "vColor" << "vDeformVec" << "vRotation"; }; void initialize() { @@ -143,58 +147,68 @@ public: QGLFunctions* glFuncs; }; -class UltraMaterial : public QSGMaterial +class DeformableMaterialData : public ImageMaterialData {}; +class DeformableMaterial : public QSGSimpleMaterialShader { + QSG_DECLARE_SIMPLE_SHADER(DeformableMaterial, DeformableMaterialData) + public: - UltraMaterial(bool withSprites=false) - : texture(0) - , colortable(0) - , sizetable(0) - , opacitytable(0) - , timestamp(0) - , framecount(1) - , animcount(1) - , usesSprites(withSprites) + DeformableMaterial() { - setFlag(Blending, true); - } + QFile vf(":defaultshaders/deformablevertex.shader"); + vf.open(QFile::ReadOnly); + m_vertex_code = vf.readAll(); - ~UltraMaterial() - { - delete texture; - delete colortable; - delete sizetable; - delete opacitytable; + QFile ff(":defaultshaders/deformablefragment.shader"); + ff.open(QFile::ReadOnly); + m_fragment_code = ff.readAll(); + + Q_ASSERT(!m_vertex_code.isNull()); + Q_ASSERT(!m_fragment_code.isNull()); } - virtual QSGMaterialType *type() const { static QSGMaterialType type; return &type; } - virtual QSGMaterialShader *createShader() const; - virtual int compare(const QSGMaterial *other) const - { - return this - static_cast(other); + const char *vertexShader() const { return m_vertex_code.constData(); } + const char *fragmentShader() const { return m_fragment_code.constData(); } + + QList attributes() const { + return QList() << "vPos" << "vTex" << "vData" << "vVec" + << "vColor" << "vDeformVec" << "vRotation"; + }; + + void initialize() { + QSGSimpleMaterialShader::initialize(); + program()->bind(); + program()->setUniformValue("texture", 0); + glFuncs = QGLContext::currentContext()->functions(); + m_timestamp_id = program()->uniformLocation("timestamp"); } - QSGTexture *texture; - QSGTexture *colortable; - QSGTexture *sizetable; - QSGTexture *opacitytable; + void updateState(const DeformableMaterialData* d, const DeformableMaterialData*) { + glFuncs->glActiveTexture(GL_TEXTURE0); + d->texture->bind(); - qreal timestamp; - int framecount; - int animcount; - bool usesSprites; + program()->setUniformValue(m_timestamp_id, (float) d->timestamp); + } + int m_timestamp_id; + QByteArray m_vertex_code; + QByteArray m_fragment_code; + QGLFunctions* glFuncs; }; -class UltraMaterialData : public QSGMaterialShader + +class SpriteMaterialData : public ImageMaterialData {}; +class SpriteMaterial : public QSGSimpleMaterialShader { + QSG_DECLARE_SIMPLE_SHADER(SpriteMaterial, SpriteMaterialData) + public: - UltraMaterialData(const char *vertexFile = 0, const char *fragmentFile = 0) + SpriteMaterial() { - QFile vf(vertexFile ? vertexFile : ":defaultshaders/ultravertex.shader"); + QFile vf(":defaultshaders/spritevertex.shader"); vf.open(QFile::ReadOnly); m_vertex_code = vf.readAll(); - QFile ff(fragmentFile ? fragmentFile : ":defaultshaders/ultrafragment.shader"); + QFile ff(":defaultshaders/spritefragment.shader"); ff.open(QFile::ReadOnly); m_fragment_code = ff.readAll(); @@ -202,110 +216,67 @@ public: Q_ASSERT(!m_fragment_code.isNull()); } - void deactivate() { - QSGMaterialShader::deactivate(); - - for (int i=0; i<8; ++i) { - program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0); - } - } - - virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *) - { - UltraMaterial *m = static_cast(newEffect); - state.context()->functions()->glActiveTexture(GL_TEXTURE1); - m->colortable->bind(); - - state.context()->functions()->glActiveTexture(GL_TEXTURE2); - m->sizetable->bind(); - - state.context()->functions()->glActiveTexture(GL_TEXTURE3); - m->opacitytable->bind(); - - // make sure we end by setting GL_TEXTURE0 as active texture - state.context()->functions()->glActiveTexture(GL_TEXTURE0); - m->texture->bind(); - - program()->setUniformValue(m_opacity_id, state.opacity()); - program()->setUniformValue(m_timestamp_id, (float) m->timestamp); - program()->setUniformValue(m_framecount_id, (float) m->framecount); - program()->setUniformValue(m_animcount_id, (float) m->animcount); + const char *vertexShader() const { return m_vertex_code.constData(); } + const char *fragmentShader() const { return m_fragment_code.constData(); } - if (state.isMatrixDirty()) - program()->setUniformValue(m_matrix_id, state.combinedMatrix()); - } + QList attributes() const { + return QList() << "vPos" << "vTex" << "vData" << "vVec" + << "vColor" << "vDeformVec" << "vRotation" << "vAnimData"; + }; - virtual void initialize() { + void initialize() { + QSGSimpleMaterialShader::initialize(); program()->bind(); program()->setUniformValue("texture", 0); program()->setUniformValue("colortable", 1); program()->setUniformValue("sizetable", 2); program()->setUniformValue("opacitytable", 3); - m_matrix_id = program()->uniformLocation("matrix"); - m_opacity_id = program()->uniformLocation("opacity"); + glFuncs = QGLContext::currentContext()->functions(); m_timestamp_id = program()->uniformLocation("timestamp"); m_framecount_id = program()->uniformLocation("framecount"); m_animcount_id = program()->uniformLocation("animcount"); } - virtual const char *vertexShader() const { return m_vertex_code.constData(); } - virtual const char *fragmentShader() const { return m_fragment_code.constData(); } - - virtual char const *const *attributeNames() const { - static const char *attr[] = { - "vPos", - "vTex", - "vData", - "vVec", - "vColor", - "vDeformVec", - "vRotation", - "vAnimData", - 0 - }; - return attr; - } + void updateState(const SpriteMaterialData* d, const SpriteMaterialData*) { + glFuncs->glActiveTexture(GL_TEXTURE1); + d->colortable->bind(); - virtual bool isColorTable() const { return false; } + glFuncs->glActiveTexture(GL_TEXTURE2); + d->sizetable->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(); + + program()->setUniformValue(m_timestamp_id, (float) d->timestamp); + program()->setUniformValue(m_framecount_id, (float) d->framecount); + program()->setUniformValue(m_animcount_id, (float) d->animcount); + } - int m_matrix_id; - int m_opacity_id; int m_timestamp_id; int m_framecount_id; int m_animcount_id; - QByteArray m_vertex_code; QByteArray m_fragment_code; - - static float chunkOfBytes[1024]; + QGLFunctions* glFuncs; }; -float UltraMaterialData::chunkOfBytes[1024]; - -QSGMaterialShader *UltraMaterial::createShader() const -{ - if (usesSprites)//TODO: Perhaps just swap the shaders, and don't mind the extra vector? - return new UltraMaterialData; - else - return new UltraMaterialData; -} - -class SimpleMaterial : public UltraMaterial +class ColoredMaterialData : public ImageMaterialData {}; +class ColoredMaterial : public QSGSimpleMaterialShader { - virtual QSGMaterialShader *createShader() const; - virtual QSGMaterialType *type() const { static QSGMaterialType type; return &type; } -}; + QSG_DECLARE_SIMPLE_SHADER(ColoredMaterial, ColoredMaterialData) -class SimpleMaterialData : public QSGMaterialShader -{ public: - SimpleMaterialData(const char *vertexFile = 0, const char *fragmentFile = 0) + ColoredMaterial() { - QFile vf(vertexFile ? vertexFile : ":defaultshaders/simplevertex.shader"); + QFile vf(":defaultshaders/coloredvertex.shader"); vf.open(QFile::ReadOnly); m_vertex_code = vf.readAll(); - QFile ff(fragmentFile ? fragmentFile : ":defaultshaders/simplefragment.shader"); + QFile ff(":defaultshaders/coloredfragment.shader"); ff.open(QFile::ReadOnly); m_fragment_code = ff.readAll(); @@ -313,63 +284,82 @@ public: Q_ASSERT(!m_fragment_code.isNull()); } - void deactivate() { - QSGMaterialShader::deactivate(); + const char *vertexShader() const { return m_vertex_code.constData(); } + const char *fragmentShader() const { return m_fragment_code.constData(); } - for (int i=0; i<8; ++i) { - program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0); - } + QList attributes() const { + return QList() << "vPos" << "vTex" << "vData" << "vVec" + << "vColor"; + } + + void initialize() { + QSGSimpleMaterialShader::initialize(); + program()->bind(); + program()->setUniformValue("texture", 0); + glFuncs = QGLContext::currentContext()->functions(); + m_timestamp_id = program()->uniformLocation("timestamp"); + } + + void updateState(const ColoredMaterialData* d, const ColoredMaterialData*) { + glFuncs->glActiveTexture(GL_TEXTURE0); + d->texture->bind(); + + program()->setUniformValue(m_timestamp_id, (float) d->timestamp); } - virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *) + int m_timestamp_id; + QByteArray m_vertex_code; + QByteArray m_fragment_code; + QGLFunctions* glFuncs; +}; + +class SimpleMaterialData : public ImageMaterialData {}; +class SimpleMaterial : public QSGSimpleMaterialShader +{ + QSG_DECLARE_SIMPLE_SHADER(SimpleMaterial, SimpleMaterialData) + +public: + SimpleMaterial() { - UltraMaterial *m = static_cast(newEffect); - state.context()->functions()->glActiveTexture(GL_TEXTURE0); - m->texture->bind(); + QFile vf(":defaultshaders/simplevertex.shader"); + vf.open(QFile::ReadOnly); + m_vertex_code = vf.readAll(); - program()->setUniformValue(m_opacity_id, state.opacity()); - program()->setUniformValue(m_timestamp_id, (float) m->timestamp); + QFile ff(":defaultshaders/simplefragment.shader"); + ff.open(QFile::ReadOnly); + m_fragment_code = ff.readAll(); - if (state.isMatrixDirty()) - program()->setUniformValue(m_matrix_id, state.combinedMatrix()); + Q_ASSERT(!m_vertex_code.isNull()); + Q_ASSERT(!m_fragment_code.isNull()); } - virtual void initialize() { - m_matrix_id = program()->uniformLocation("matrix"); - m_opacity_id = program()->uniformLocation("opacity"); - m_timestamp_id = program()->uniformLocation("timestamp"); + const char *vertexShader() const { return m_vertex_code.constData(); } + const char *fragmentShader() const { return m_fragment_code.constData(); } + + QList attributes() const { + return QList() << "vPos" << "vTex" << "vData" << "vVec"; } - virtual const char *vertexShader() const { return m_vertex_code.constData(); } - virtual const char *fragmentShader() const { return m_fragment_code.constData(); } - - virtual char const *const *attributeNames() const { - static const char *attr[] = { - "vPos", - "vTex", - "vData", - "vVec", - 0 - }; - return attr; + void initialize() { + QSGSimpleMaterialShader::initialize(); + program()->bind(); + program()->setUniformValue("texture", 0); + glFuncs = QGLContext::currentContext()->functions(); + m_timestamp_id = program()->uniformLocation("timestamp"); } - virtual bool isColorTable() const { return false; } + void updateState(const SimpleMaterialData* d, const SimpleMaterialData*) { + glFuncs->glActiveTexture(GL_TEXTURE0); + d->texture->bind(); - int m_matrix_id; - int m_opacity_id; - int m_timestamp_id; + program()->setUniformValue(m_timestamp_id, (float) d->timestamp); + } + int m_timestamp_id; QByteArray m_vertex_code; QByteArray m_fragment_code; - - static float chunkOfBytes[1024]; + QGLFunctions* glFuncs; }; -float SimpleMaterialData::chunkOfBytes[1024]; - -QSGMaterialShader *SimpleMaterial::createShader() const { - return new SimpleMaterialData; -} /*! \qmlclass ImageParticle QSGImageParticle @@ -450,7 +440,6 @@ QSGImageParticle::QSGImageParticle(QSGItem* parent) , m_color_variation(0.0) , m_rootNode(0) , m_material(0) - , m_tabledMaterial(0) , m_alphaVariation(0.0) , m_alpha(1.0) , m_redVariation(0.0) @@ -476,7 +465,6 @@ QSGImageParticle::QSGImageParticle(QSGItem* parent) QSGImageParticle::~QSGImageParticle() { delete m_material; - delete m_tabledMaterial; } QDeclarativeListProperty QSGImageParticle::sprites() @@ -703,276 +691,146 @@ static QSGGeometry::AttributeSet SimpleParticle_AttributeSet = SimpleParticle_Attributes }; -static QSGGeometry::Attribute UltraParticle_Attributes[] = { +static QSGGeometry::Attribute ColoredParticle_Attributes[] = { { 0, 2, GL_FLOAT }, // Position { 1, 2, GL_FLOAT }, // TexCoord { 2, 4, GL_FLOAT }, // Data { 3, 4, GL_FLOAT }, // Vectors { 4, 4, GL_UNSIGNED_BYTE }, // Colors - { 5, 4, GL_FLOAT }, // DeformationVectors - { 6, 3, GL_FLOAT }, // Rotation - { 7, 4, GL_FLOAT } // Anim Data }; -static QSGGeometry::AttributeSet UltraParticle_AttributeSet = +static QSGGeometry::AttributeSet ColoredParticle_AttributeSet = { - 8, // Attribute Count - (2 + 2 + 4 + 4 + 4 + 4 + 3) * sizeof(float) + 4 * sizeof(uchar), - UltraParticle_Attributes + 5, // Attribute Count + (2 + 2 + 4 + 4) * sizeof(float) + 4 * sizeof(uchar), + ColoredParticle_Attributes }; -QSGGeometryNode* QSGImageParticle::buildSimpleParticleNodes() -{ - perfLevel = Simple;//TODO: Intermediate levels - QImage image = QImage(m_image_name.toLocalFile()); - if (image.isNull()) { - printf("UltraParticle: loading image failed... '%s'\n", qPrintable(m_image_name.toLocalFile())); - return 0; - } - - if (m_material) { - delete m_material; - m_material = 0; - } - - m_material = new SimpleMaterial(); - m_material->texture = sceneGraphEngine()->createTextureFromImage(image); - m_material->texture->setFiltering(QSGTexture::Linear); - m_material->framecount = 1; - - foreach (const QString &str, m_particles){ - int gIdx = m_system->m_groupIds[str]; - int count = m_system->m_groupData[gIdx]->size(); - - QSGGeometryNode* node = new QSGGeometryNode(); - m_nodes.insert(gIdx, node); - node->setMaterial(m_material); - - int vCount = count * 4; - int iCount = count * 6; - - QSGGeometry *g = new QSGGeometry(SimpleParticle_AttributeSet, vCount, iCount); - node->setGeometry(g); - g->setDrawingMode(GL_TRIANGLES); - - SimpleVertex *vertices = (SimpleVertex *) g->vertexData(); - for (int p=0; p < count; ++p){ - commit(gIdx, p); - vertices[0].tx = 0; - vertices[0].ty = 0; - - vertices[1].tx = 1; - vertices[1].ty = 0; - - vertices[2].tx = 0; - vertices[2].ty = 1; - - vertices[3].tx = 1; - vertices[3].ty = 1; - - vertices += 4; - } - - quint16 *indices = g->indexDataAsUShort(); - for (int i=0; i < count; ++i) { - int o = i * 4; - indices[0] = o; - indices[1] = o + 1; - indices[2] = o + 2; - indices[3] = o + 1; - indices[4] = o + 3; - indices[5] = o + 2; - indices += 6; - } - } - - foreach (QSGGeometryNode* node, m_nodes){ - if (node == *(m_nodes.begin())) - continue; - (*(m_nodes.begin()))->appendChildNode(node); - } - - return *(m_nodes.begin()); -} +static QSGGeometry::Attribute DeformableParticle_Attributes[] = { + { 0, 2, GL_FLOAT }, // Position + { 1, 2, GL_FLOAT }, // TexCoord + { 2, 4, GL_FLOAT }, // Data + { 3, 4, GL_FLOAT }, // Vectors + { 4, 4, GL_UNSIGNED_BYTE }, // Colors + { 5, 4, GL_FLOAT }, // DeformationVectors + { 6, 3, GL_FLOAT }, // Rotation +}; -QSGGeometryNode* QSGImageParticle::buildTabledParticleNodes()//TODO: TabledParticle so as to not have the unused anim attributes +static QSGGeometry::AttributeSet DeformableParticle_AttributeSet = { - perfLevel = Tabled;//TODO: More Intermediate levels - if (!m_color.isValid())//But we're in colored level (or higher) - m_color = QColor(Qt::white); - QImage image = QImage(m_image_name.toLocalFile()); - if (image.isNull()) { - printf("ImageParticle: loading image failed... '%s'\n", qPrintable(m_image_name.toLocalFile())); - return 0; - } - - if (m_material) { - delete m_material; - m_material = 0; - } - - m_tabledMaterial = TabledMaterial::createMaterial(); - m_tabledMaterial->setFlag(QSGMaterial::Blending, true); - QImage colortable(m_colortable_name.toLocalFile()); - QImage sizetable(m_sizetable_name.toLocalFile()); - QImage opacitytable(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()); - m_tabledMaterial->state()->colortable = sceneGraphEngine()->createTextureFromImage(colortable); - m_tabledMaterial->state()->sizetable = sceneGraphEngine()->createTextureFromImage(sizetable); - m_tabledMaterial->state()->opacitytable = sceneGraphEngine()->createTextureFromImage(opacitytable); - m_tabledMaterial->state()->texture = sceneGraphEngine()->createTextureFromImage(image); - m_tabledMaterial->state()->texture->setFiltering(QSGTexture::Linear); - - foreach (const QString &str, m_particles){ - int gIdx = m_system->m_groupIds[str]; - int count = m_system->m_groupData[gIdx]->size(); - QSGGeometryNode* node = new QSGGeometryNode(); - node->setMaterial(m_tabledMaterial); - - m_nodes.insert(gIdx, node); - m_idxStarts.insert(gIdx, m_lastIdxStart); - m_lastIdxStart += count; - - //Create Particle Geometry - int vCount = count * 4; - int iCount = count * 6; - - QSGGeometry *g = new QSGGeometry(UltraParticle_AttributeSet, vCount, iCount); - node->setGeometry(g); - g->setDrawingMode(GL_TRIANGLES); - - UltraVertex *vertices = (UltraVertex *) g->vertexData(); - for (int p=0; p < count; ++p) { - commit(gIdx, p);//commit sets geometry for the node - - vertices[0].tx = 0; - vertices[0].ty = 0; - - vertices[1].tx = 1; - vertices[1].ty = 0; - - vertices[2].tx = 0; - vertices[2].ty = 1; - - vertices[3].tx = 1; - vertices[3].ty = 1; - - vertices += 4; - } - - quint16 *indices = g->indexDataAsUShort(); - for (int i=0; i < count; ++i) { - int o = i * 4; - indices[0] = o; - indices[1] = o + 1; - indices[2] = o + 2; - indices[3] = o + 1; - indices[4] = o + 3; - indices[5] = o + 2; - indices += 6; - } - - } - - + 7, // Attribute Count + (2 + 2 + 4 + 4 + 4 + 3) * sizeof(float) + 4 * sizeof(uchar), + DeformableParticle_Attributes +}; - foreach (QSGGeometryNode* node, m_nodes){ - if (node == *(m_nodes.begin())) - continue; - (*(m_nodes.begin()))->appendChildNode(node); - } +static QSGGeometry::Attribute SpriteParticle_Attributes[] = { + { 0, 2, GL_FLOAT }, // Position + { 1, 2, GL_FLOAT }, // TexCoord + { 2, 4, GL_FLOAT }, // Data + { 3, 4, GL_FLOAT }, // Vectors + { 4, 4, GL_UNSIGNED_BYTE }, // Colors + { 5, 4, GL_FLOAT }, // DeformationVectors + { 6, 3, GL_FLOAT }, // Rotation + { 7, 4, GL_FLOAT } // Anim Data +}; - return *(m_nodes.begin()); -} +static QSGGeometry::AttributeSet SpriteParticle_AttributeSet = +{ + 8, // Attribute Count + (2 + 2 + 4 + 4 + 4 + 4 + 3) * sizeof(float) + 4 * sizeof(uchar), + SpriteParticle_Attributes +}; QSGGeometryNode* QSGImageParticle::buildParticleNodes() { - if (m_count * 4 > 0xffff) { - printf("UltraParticle: Too many particles... \n");//### Why is this here? + if (m_count * 4 > 0xffff) {//TODO: Lift this limit for desktop? + printf("ImageParticle: Too many particles - maximum 16,000 per ImageParticle.\n");//ES 2 vertex count limit is ushort return 0; } if (count() <= 0) return 0; - if (!m_sprites.count() && !m_bloat) { - if (m_colortable_name.isEmpty() - && m_sizetable_name.isEmpty() - && m_opacitytable_name.isEmpty() - && !m_autoRotation - && !m_rotation && !m_rotationVariation - && !m_rotationSpeed && !m_rotationSpeedVariation - && !m_alphaVariation && m_alpha == 1.0 - && !m_redVariation && !m_blueVariation && !m_greenVariation - && !m_color.isValid() - ) - return buildSimpleParticleNodes(); - else - return buildTabledParticleNodes(); - } - if (m_tabledMaterial) { - delete m_tabledMaterial; - m_tabledMaterial = 0; + if (m_sprites.count() || m_bloat) { + perfLevel = Sprites; + } else if (!m_colortable_name.isEmpty() || !m_sizetable_name.isEmpty() + || !m_opacitytable_name.isEmpty()) { + perfLevel = Tabled; + } else if (m_autoRotation || m_rotation || m_rotationVariation + || m_rotationSpeed || m_rotationSpeedVariation) { + perfLevel = Deformable; + } else if (m_alphaVariation || m_alpha != 1.0 || m_color.isValid() + || m_redVariation || m_blueVariation || m_greenVariation) { + perfLevel = Colored; + } else { + perfLevel = Simple; } - perfLevel = Sprites;//TODO: intermediate levels - if (!m_color.isValid())//But we're in colored level (or higher) - m_color = QColor(Qt::white); + if (perfLevel >= Colored && !m_color.isValid()) + m_color = QColor(Qt::white);//Hidden default, but different from unset QImage image; - if (m_sprites.count()){ + if (perfLevel >= Sprites){ if (!m_spriteEngine) { - qWarning() << "UltraParticle: No sprite engine..."; + qWarning() << "ImageParticle: No sprite engine..."; return 0; } image = m_spriteEngine->assembledImage(); if (image.isNull())//Warning is printed in engine return 0; - }else{ + } else { image = QImage(m_image_name.toLocalFile()); if (image.isNull()) { - printf("UltraParticle: loading image failed... '%s'\n", qPrintable(m_image_name.toLocalFile())); + printf("ImageParticle: loading image failed '%s'\n", qPrintable(m_image_name.toLocalFile())); return 0; } } + if (m_material) { delete m_material; m_material = 0; } - QImage colortable(m_colortable_name.toLocalFile()); - QImage sizetable(m_sizetable_name.toLocalFile()); - QImage opacitytable(m_opacitytable_name.toLocalFile()); - m_material = new UltraMaterial(); - 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()); - m_material->colortable = sceneGraphEngine()->createTextureFromImage(colortable); - m_material->sizetable = sceneGraphEngine()->createTextureFromImage(sizetable); - m_material->opacitytable = sceneGraphEngine()->createTextureFromImage(opacitytable); - - m_material->texture = sceneGraphEngine()->createTextureFromImage(image); - m_material->texture->setFiltering(QSGTexture::Linear); - - m_material->framecount = 1; - if (m_spriteEngine){ - m_material->framecount = m_spriteEngine->maxFrames(); + //Setup material + QImage colortable; + QImage sizetable; + QImage opacitytable; + switch (perfLevel) {//Fallthrough intended + case Sprites: + m_material = SpriteMaterial::createMaterial(); + getState(m_material)->framecount = m_spriteEngine->maxFrames(); m_spriteEngine->setCount(m_count); + case Tabled: + if (!m_material) + m_material = TabledMaterial::createMaterial(); + colortable = QImage(m_colortable_name.toLocalFile()); + sizetable = QImage(m_sizetable_name.toLocalFile()); + 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(m_material)->colortable = sceneGraphEngine()->createTextureFromImage(colortable); + getState(m_material)->sizetable = sceneGraphEngine()->createTextureFromImage(sizetable); + getState(m_material)->opacitytable = sceneGraphEngine()->createTextureFromImage(opacitytable); + case Deformable: + if (!m_material) + m_material = DeformableMaterial::createMaterial(); + case Colored: + if (!m_material) + m_material = ColoredMaterial::createMaterial(); + default://Also Simple + if (!m_material) + m_material = SimpleMaterial::createMaterial(); + getState(m_material)->texture = sceneGraphEngine()->createTextureFromImage(image); + getState(m_material)->texture->setFiltering(QSGTexture::Linear); + m_material->setFlag(QSGMaterial::Blending); } foreach (const QString &str, m_particles){ @@ -989,28 +847,34 @@ QSGGeometryNode* QSGImageParticle::buildParticleNodes() int vCount = count * 4; int iCount = count * 6; - QSGGeometry *g = new QSGGeometry(UltraParticle_AttributeSet, vCount, iCount); + QSGGeometry *g; + if (perfLevel == Sprites) + g = new QSGGeometry(SpriteParticle_AttributeSet, vCount, iCount); + else if (perfLevel == Tabled) + g = new QSGGeometry(DeformableParticle_AttributeSet, vCount, iCount); + else if (perfLevel == Deformable) + g = new QSGGeometry(DeformableParticle_AttributeSet, vCount, iCount); + else if (perfLevel == Colored) + g = new QSGGeometry(ColoredParticle_AttributeSet, vCount, iCount); + else //Simple + g = new QSGGeometry(SimpleParticle_AttributeSet, vCount, iCount); + node->setGeometry(g); g->setDrawingMode(GL_TRIANGLES); - UltraVertex *vertices = (UltraVertex *) g->vertexData(); - for (int p=0; p < count; ++p) { - commit(gIdx, p);//commit sets geometry for the node - - vertices[0].tx = 0; - vertices[0].ty = 0; - - vertices[1].tx = 1; - vertices[1].ty = 0; - - vertices[2].tx = 0; - vertices[2].ty = 1; - - vertices[3].tx = 1; - vertices[3].ty = 1; + for (int p=0; p < count; ++p) + commit(gIdx, p);//commit sets geometry for the node, has its own perfLevel switch - vertices += 4; - } + if (perfLevel == Sprites) + initTexCoords((SpriteVertex*)g->vertexData(), vCount); + else if (perfLevel == Tabled) + initTexCoords((DeformableVertex*)g->vertexData(), vCount); + else if (perfLevel == Deformable) + initTexCoords((DeformableVertex*)g->vertexData(), vCount); + else if (perfLevel == Colored) + initTexCoords((ColoredVertex*)g->vertexData(), vCount); + else //Simple + initTexCoords((SimpleVertex*)g->vertexData(), vCount); quint16 *indices = g->indexDataAsUShort(); for (int i=0; i < count; ++i) { @@ -1087,42 +951,34 @@ void QSGImageParticle::prepareNextFrame() qreal time = timeStamp / 1000.; - switch (perfLevel){//Fall-through intended... eventually //TODO: solve m_material/m_namedMaterial! + switch (perfLevel){//Fall-through intended case Sprites: - m_material->timestamp = time; //Advance State - if (m_spriteEngine){//perfLevel == Sprites?//TODO: use signals? - - m_material->animcount = m_spriteEngine->spriteCount(); - m_spriteEngine->updateSprites(timeStamp); - foreach (const QString &str, m_particles){ - int gIdx = m_system->m_groupIds[str]; - int count = m_system->m_groupData[gIdx]->size(); - - UltraVertices *particles = (UltraVertices *) m_nodes[gIdx]->geometry()->vertexData(); - for (int i=0; i < count; i++){ - int spriteIdx = m_idxStarts[gIdx] + i; - UltraVertices &p = particles[i]; - int curIdx = m_spriteEngine->spriteState(spriteIdx); - if (curIdx != p.v1.animIdx){ - p.v1.animIdx = p.v2.animIdx = p.v3.animIdx = p.v4.animIdx = curIdx; - p.v1.animT = p.v2.animT = p.v3.animT = p.v4.animT = m_spriteEngine->spriteStart(spriteIdx)/1000.0; - p.v1.frameCount = p.v2.frameCount = p.v3.frameCount = p.v4.frameCount = m_spriteEngine->spriteFrames(spriteIdx); - p.v1.frameDuration = p.v2.frameDuration = p.v3.frameDuration = p.v4.frameDuration = m_spriteEngine->spriteDuration(spriteIdx); - } + getState(m_material)->animcount = m_spriteEngine->spriteCount(); + m_spriteEngine->updateSprites(timeStamp); + foreach (const QString &str, m_particles){ + int gIdx = m_system->m_groupIds[str]; + int count = m_system->m_groupData[gIdx]->size(); + + Vertices* particles = (Vertices *) m_nodes[gIdx]->geometry()->vertexData(); + for (int i=0; i < count; i++){ + int spriteIdx = m_idxStarts[gIdx] + i; + Vertices &p = particles[i]; + int curIdx = m_spriteEngine->spriteState(spriteIdx); + if (curIdx != p.v1.animIdx){ + p.v1.animIdx = p.v2.animIdx = p.v3.animIdx = p.v4.animIdx = curIdx; + p.v1.animT = p.v2.animT = p.v3.animT = p.v4.animT = m_spriteEngine->spriteStart(spriteIdx)/1000.0; + p.v1.frameCount = p.v2.frameCount = p.v3.frameCount = p.v4.frameCount = m_spriteEngine->spriteFrames(spriteIdx); + p.v1.frameDuration = p.v2.frameDuration = p.v3.frameDuration = p.v4.frameDuration = m_spriteEngine->spriteDuration(spriteIdx); } } - }else{ - m_material->animcount = 1; } - break; case Tabled: case Deformable: case Colored: - m_tabledMaterial->state()->timestamp = time; break; case Simple: - m_material->timestamp = time; break; - default: + default: //Also Simple + getState(m_material)->timestamp = time; break; } @@ -1194,69 +1050,88 @@ void QSGImageParticle::commit(int gIdx, int pIdx) if (!node) return; QSGParticleData* datum = m_system->m_groupData[gIdx]->data[pIdx]; - node->setFlag(QSGNode::OwnsGeometry, false); - UltraVertex *ultraVertices = (UltraVertex *) node->geometry()->vertexData(); + SpriteVertex *spriteVertices = (SpriteVertex *) node->geometry()->vertexData(); + DeformableVertex *deformableVertices = (DeformableVertex *) node->geometry()->vertexData(); + ColoredVertex *coloredVertices = (ColoredVertex *) node->geometry()->vertexData(); SimpleVertex *simpleVertices = (SimpleVertex *) node->geometry()->vertexData(); - switch (perfLevel){ + switch (perfLevel){//No automatic fall through intended on this one case Sprites: - ultraVertices += pIdx*4; + spriteVertices += pIdx*4; for (int i=0; i<4; i++){ - ultraVertices[i].x = datum->x - m_systemOffset.x(); - ultraVertices[i].y = datum->y - m_systemOffset.y(); - ultraVertices[i].t = datum->t; - ultraVertices[i].lifeSpan = datum->lifeSpan; - ultraVertices[i].size = datum->size; - ultraVertices[i].endSize = datum->endSize; - ultraVertices[i].vx = datum->vx; - ultraVertices[i].vy = datum->vy; - ultraVertices[i].ax = datum->ax; - ultraVertices[i].ay = datum->ay; - ultraVertices[i].xx = datum->xx; - ultraVertices[i].xy = datum->xy; - ultraVertices[i].yx = datum->yx; - ultraVertices[i].yy = datum->yy; - ultraVertices[i].rotation = datum->rotation; - ultraVertices[i].rotationSpeed = datum->rotationSpeed; - ultraVertices[i].autoRotate = datum->autoRotate; - ultraVertices[i].animIdx = datum->animIdx; - ultraVertices[i].frameDuration = datum->frameDuration; - ultraVertices[i].frameCount = datum->frameCount; - ultraVertices[i].animT = datum->animT; - ultraVertices[i].color.r = datum->color.r; - ultraVertices[i].color.g = datum->color.g; - ultraVertices[i].color.b = datum->color.b; - ultraVertices[i].color.a = datum->color.a; + spriteVertices[i].x = datum->x - m_systemOffset.x(); + spriteVertices[i].y = datum->y - m_systemOffset.y(); + spriteVertices[i].t = datum->t; + spriteVertices[i].lifeSpan = datum->lifeSpan; + spriteVertices[i].size = datum->size; + spriteVertices[i].endSize = datum->endSize; + spriteVertices[i].vx = datum->vx; + spriteVertices[i].vy = datum->vy; + spriteVertices[i].ax = datum->ax; + spriteVertices[i].ay = datum->ay; + spriteVertices[i].xx = datum->xx; + spriteVertices[i].xy = datum->xy; + spriteVertices[i].yx = datum->yx; + spriteVertices[i].yy = datum->yy; + spriteVertices[i].rotation = datum->rotation; + spriteVertices[i].rotationSpeed = datum->rotationSpeed; + spriteVertices[i].autoRotate = datum->autoRotate; + spriteVertices[i].animIdx = datum->animIdx; + spriteVertices[i].frameDuration = datum->frameDuration; + spriteVertices[i].frameCount = datum->frameCount; + spriteVertices[i].animT = datum->animT; + spriteVertices[i].color.r = datum->color.r; + spriteVertices[i].color.g = datum->color.g; + spriteVertices[i].color.b = datum->color.b; + spriteVertices[i].color.a = datum->color.a; } break; - case Tabled: - ultraVertices += pIdx*4; + case Tabled: //Fall through until it has its own vertex class + case Deformable: + deformableVertices += pIdx*4; for (int i=0; i<4; i++){ - ultraVertices[i].x = datum->x - m_systemOffset.x(); - ultraVertices[i].y = datum->y - m_systemOffset.y(); - ultraVertices[i].t = datum->t; - ultraVertices[i].lifeSpan = datum->lifeSpan; - ultraVertices[i].size = datum->size; - ultraVertices[i].endSize = datum->endSize; - ultraVertices[i].vx = datum->vx; - ultraVertices[i].vy = datum->vy; - ultraVertices[i].ax = datum->ax; - ultraVertices[i].ay = datum->ay; - ultraVertices[i].xx = datum->xx; - ultraVertices[i].xy = datum->xy; - ultraVertices[i].yx = datum->yx; - ultraVertices[i].yy = datum->yy; - ultraVertices[i].rotation = datum->rotation; - ultraVertices[i].rotationSpeed = datum->rotationSpeed; - ultraVertices[i].autoRotate = datum->autoRotate; - ultraVertices[i].color.r = datum->color.r; - ultraVertices[i].color.g = datum->color.g; - ultraVertices[i].color.b = datum->color.b; - ultraVertices[i].color.a = datum->color.a; + deformableVertices[i].x = datum->x - m_systemOffset.x(); + deformableVertices[i].y = datum->y - m_systemOffset.y(); + deformableVertices[i].t = datum->t; + deformableVertices[i].lifeSpan = datum->lifeSpan; + deformableVertices[i].size = datum->size; + deformableVertices[i].endSize = datum->endSize; + deformableVertices[i].vx = datum->vx; + deformableVertices[i].vy = datum->vy; + deformableVertices[i].ax = datum->ax; + deformableVertices[i].ay = datum->ay; + deformableVertices[i].xx = datum->xx; + deformableVertices[i].xy = datum->xy; + deformableVertices[i].yx = datum->yx; + deformableVertices[i].yy = datum->yy; + deformableVertices[i].rotation = datum->rotation; + deformableVertices[i].rotationSpeed = datum->rotationSpeed; + deformableVertices[i].autoRotate = datum->autoRotate; + deformableVertices[i].color.r = datum->color.r; + deformableVertices[i].color.g = datum->color.g; + deformableVertices[i].color.b = datum->color.b; + deformableVertices[i].color.a = datum->color.a; } break; - case Deformable: //TODO: Us case Colored: + coloredVertices += pIdx*4; + for (int i=0; i<4; i++){ + coloredVertices[i].x = datum->x - m_systemOffset.x(); + coloredVertices[i].y = datum->y - m_systemOffset.y(); + coloredVertices[i].t = datum->t; + coloredVertices[i].lifeSpan = datum->lifeSpan; + coloredVertices[i].size = datum->size; + coloredVertices[i].endSize = datum->endSize; + coloredVertices[i].vx = datum->vx; + coloredVertices[i].vy = datum->vy; + coloredVertices[i].ax = datum->ax; + coloredVertices[i].ay = datum->ay; + coloredVertices[i].color.r = datum->color.r; + coloredVertices[i].color.g = datum->color.g; + coloredVertices[i].color.b = datum->color.b; + coloredVertices[i].color.a = datum->color.a; + } + break; case Simple: simpleVertices += pIdx*4; for (int i=0; i<4; i++){ diff --git a/src/declarative/particles/qsgimageparticle_p.h b/src/declarative/particles/qsgimageparticle_p.h index ae80434..f8a57a5 100644 --- a/src/declarative/particles/qsgimageparticle_p.h +++ b/src/declarative/particles/qsgimageparticle_p.h @@ -52,8 +52,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) -class UltraMaterial; -class TabledMaterialData; +class ImageMaterialData; class QSGGeometryNode; class QSGSprite; @@ -74,14 +73,46 @@ struct SimpleVertex { float ay; }; -struct SimpleVertices { - SimpleVertex v1; - SimpleVertex v2; - SimpleVertex v3; - SimpleVertex v4; +struct ColoredVertex { + float x; + float y; + float tx; + float ty; + float t; + float lifeSpan; + float size; + float endSize; + float vx; + float vy; + float ax; + float ay; + Color4ub color; +}; + +struct DeformableVertex { + float x; + float y; + float tx; + float ty; + float t; + float lifeSpan; + float size; + float endSize; + float vx; + float vy; + float ax; + float ay; + Color4ub color; + float xx; + float xy; + float yx; + float yy; + float rotation; + float rotationSpeed; + float autoRotate;//Assumed that GPUs prefer floats to bools }; -struct UltraVertex { +struct SpriteVertex { float x; float y; float tx; @@ -101,25 +132,19 @@ struct UltraVertex { float yy; float rotation; float rotationSpeed; - float autoRotate;//Assume that GPUs prefer floats to bools + float autoRotate;//Assumed that GPUs prefer floats to bools float animIdx; float frameDuration; float frameCount; float animT; }; -struct UltraVertices { - UltraVertex v1; - UltraVertex v2; - UltraVertex v3; - UltraVertex v4; -}; - -struct IntermediateVertices { - UltraVertex* v1; - UltraVertex* v2; - UltraVertex* v3; - UltraVertex* v4; +template +struct Vertices { + Vertex v1; + Vertex v2; + Vertex v3; + Vertex v4; }; class QSGImageParticle : public QSGParticlePainter @@ -292,8 +317,6 @@ protected: QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *); void prepareNextFrame(); QSGGeometryNode* buildParticleNodes(); - QSGGeometryNode* buildSimpleParticleNodes(); - QSGGeometryNode* buildTabledParticleNodes(); private slots: void createEngine(); //### method invoked by sprite list changing (in engine.h) - pretty nasty @@ -315,8 +338,7 @@ private: QHash m_nodes; QHash m_idxStarts;//TODO: Proper resizing will lead to needing a spriteEngine per particle - do this after sprite engine gains transparent sharing? int m_lastIdxStart; - UltraMaterial *m_material; - QSGSimpleMaterial *m_tabledMaterial; + QSGMaterial *m_material; // derived values... @@ -342,6 +364,31 @@ private: PerformanceLevel m_lastLevel; bool m_debugMode; + + template + void initTexCoords(Vertex* v, int count){ + Vertex* end = v + count; + while (v < end){ + v[0].tx = 0; + v[0].ty = 0; + + v[1].tx = 1; + v[1].ty = 0; + + v[2].tx = 0; + v[2].ty = 1; + + v[3].tx = 1; + v[3].ty = 1; + + v += 4; + } + } + + template + MaterialData* getState(QSGMaterial* m){ + return static_cast *>(m)->state(); + } }; QT_END_NAMESPACE