Game Development Community

UseInvAlpha particle problems

by Ian Omroth Hardingham · in Torque Game Engine · 06/13/2005 (1:53 pm) · 5 replies

Hi everyone.

I'm getting some problems with flashing using the particles shown below. I found this forum post:

http://www.garagegames.com/mg/forums/result.thread.php?qt=3974

which goes into some detail involving timings etc. I've followed the advice (as much as I could follow it) but haven't managed to fix the flashing. However, if I put "useInvAlpha" to false the flashing goes away. This isn't a whole lot of use though, as I need the alpha inverted!

Can anyone provide insight?

Any help much appreciated,
Ian

datablock ParticleData(EnergyGridB) {
   dragCoefficient = "0.171065";
   windCoefficient = "1";
   gravityCoefficient = "0.78";
   inheritedVelFactor = "1.26";
   constantAcceleration = "2.1";
   lifetimeMS = "1600";
   lifetimeVarianceMS = "0";
   spinSpeed = "0.24";
   spinRandomMin = "-30";
   spinRandomMax = "0.5";
   useInvAlpha = "1";
   animateTexture = "0";
   framesPerSec = "1";
   textureName = "dt/data/particles/smoke";
   colors[0] = "0.496063 0.496063 0.496063 0.086614";
   colors[1] = "0.000000 0.000000 0.000000 0.188976";
   colors[2] = "0.188976 0.188976 0.188976 0.000000";
   colors[3] = "0.000000 0.000000 0.000000 0.000000";
   sizes[0] = "3.1";
   sizes[1] = "1.6";
   sizes[2] = "1.7";
   sizes[3] = "0";
   times[0] = "2";
   times[1] = "6";
   times[2] = "9";
   times[3] = "1";
};

datablock ParticleData(EGSparks) {
   dragCoefficient = "0.15";
   windCoefficient = "1.14";
   gravityCoefficient = "0.42";
   inheritedVelFactor = "0.195";
   constantAcceleration = "2.2";
   lifetimeMS = "1028";
   lifetimeVarianceMS = "1027";
   spinSpeed = "0";
   spinRandomMin = "-30";
   spinRandomMax = "0.5";
   useInvAlpha = "0";
   animateTexture = "0";
   framesPerSec = "1";
   textureName = "dt/data/particles/spark";
   colors[0] = "0.500000 0.500000 1.000000 0.500000";
   colors[1] = "0.200000 0.400000 1.000000 1.000000";
   colors[2] = "0.000000 0.000000 0.000000 0.000000";
   colors[3] = "0.000000 0.000000 0.000000 0.000000";
   sizes[0] = "0.4";
   sizes[1] = "0.2";
   sizes[2] = "0";
   sizes[3] = "10";
   times[0] = "2";
   times[1] = "6";
   times[2] = "9";
   times[3] = "1.0";
};



datablock ParticleEmitterData(PlayerEGEmitter)
{
   ejectionPeriodMS = 20;
   periodVarianceMS = 5;

   ejectionVelocity = 0.25;
   velocityVariance = 0;

   thetaMin = 0.0;
   thetaMax = 90.0;

   particles = "EGSparks\tEnergyGridB";

   ////////////

   //ejectionOffset = 0.09;
   
   phiReferenceVel = 0;
   phiVariance = 360;
   overrideAdvance = 0;
   orientParticles = 1;
   orientOnVelocity = 1;
   
   //lifetimeMS = 420; <--- Evil!
   lifetimeVarianceMS = 0;
   //useEmitterSizes = 0;
   //useEmitterColors = 0;
};

#1
06/13/2005 (2:46 pm)
Funny you should mention this.. I just fixed this issue for my game a few days ago. I'll see if I can remember what I did...

Ah yes. InvAlpha and non-InvAlpha particles don't mix, because when the emitter goes to render its particles, it chooses its blending method based on the useInvAlpha flag of the first, and only the first, particle in the list. If your emitter has mixed types, this means that all the particles from that emitter will be rendered with the same blending method, which is essentially choosen randomly each frame. The results is a rather ugly "flashing" effect.

Anyhow.. Here's my fix: In particleEngine.cc, find the renderObject function. Make changes like so:

void ParticleEmitter::renderObject(SceneState* state, SceneRenderImage*)
{
   AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on entry");

   [i]... some code here not shown ...[/i]

   glEnable(GL_BLEND);
   glEnable(GL_TEXTURE_2D);
   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE);
   glDepthMask(GL_FALSE);


   [b]// sr: removed this. see below.
   //if( orderedVector.size() > 0 && orderedVector[0].p->dataBlock->useInvAlpha )
   //{
   //   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   //}[/b]


   Point3F basePoints[4];
   basePoints[0] = Point3F(-1.0, 0.0, -1.0);
   basePoints[1] = Point3F( 1.0, 0.0, -1.0);
   basePoints[2] = Point3F( 1.0, 0.0,  1.0);
   basePoints[3] = Point3F(-1.0, 0.0,  1.0);

   F32 spinFactor = (1.0/1000.0) * (1.0/360.0) * M_PI * 2.0;


   [b]// sr: adding this for efficiency
   bool prevInvAlpha = false;[/b]
   
   for (U32 i = 0; i < orderedVector.size(); i++) {
      Particle* particle = orderedVector[ i ].p;
      
      [b]// sr: adding this. I think this will fix the rendering problems when mixing InvAlpha and non-InvAlpha particles
      if (particle->dataBlock->useInvAlpha != prevInvAlpha) {
         if (particle->dataBlock->useInvAlpha)
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
         else
            glBlendFunc(GL_SRC_ALPHA, GL_ONE);
         prevInvAlpha = particle->dataBlock->useInvAlpha;
      }[/b]

      if( particle->dataBlock->animateTexture )
      {
   
      [i]... etc. leave the rest of this function as is ...[/i]

This change has worked well for me. I should mention I'm working off a 1.3 version of Torque here. Hope that helps.
#2
06/14/2005 (6:21 am)
Scott, you are an absolute legend, that works perfectly. This really needs to be added to head.

You potentially saved me a hell of a lot of time with this one Scott, thankyou.

Ian
#3
06/14/2005 (12:05 pm)
Nice fix, Scott. I've put in the bugtracker.
#4
07/12/2005 (2:35 pm)
Bug #94 resolved. Also optimized a vector.
#5
07/12/2005 (2:41 pm)
Ben seems to be on a bug rampage!