- Basic ParticleEffect usage
- Efficiently using ParticleEffects
- Examples
- Pooled Effect example
- Batched Effect example
- Video example
Basic ParticleEffect usage
ParticleEditorTextureAtlas particleAtlas; //<-load some atlas with your particle assets inParticleEffect effect = new ParticleEffect();effect.load(Gdx.files.internal("myparticle.p"), particleAtlas);effect.start();//Setting the position of the ParticleEffecteffect.setPosition(x, y);//Updating and Drawing the particle effect//Delta being the time to progress the particle effect by, usually you pass in Gdx.graphics.getDeltaTime();effect.draw(batch, delta);
Efficiency
Rendering particles is great, rendering lots of particles is even better, here is how you do it without melting your users devices. ARE sprites. Take everything you know already about efficiently rendering sprites and carry them across. - If your particle effect sprite shares a texture with all of your other gameplay assets, or at least the ones that are being batched together, you wont have to switch textures, which causes the Batch to flush. You don’t want the batch to flush too often as its an expensive operation, and you won’t get the most out of your Batch. -ParticleEffectPoolcompletely mitigates garbage generation as you will be reusing yourParticleEffectwhen you are finished with them. No more wasted memory! No more garbage collection In simple terms, grab a new object from the Pool, use it, when you are finished, return it so you can use it again. the example below for how to implement pooling. - Batch your effects Draw all your ParticleEffects that have the same Textures/blend modes together. We don’t want to interrupt the Batch, which means no texture swapping, no blend state changing. This gets the most out of our Batch, and keeps our device happy.
If you have ParticleEffects that have different blending, for example some may have Additive, and others dont, group them together when you draw so you only swap the blend mode once.
Spritethat belongs to a differentTexturethan another effect. Draw all your instances that use the same Texture first, then the rest. If you interleave these ParticleEffects with different Textures, you will be causing lots of draw calls. See the example below for how to implement batching. Batch. By default the ParticleEffect returns the Batch’s state to the original state it was in, so the following draws are not effected by the ParticleEffect’s blend mode. This is great, apart from if you want to draw multiple ParticleEffect instances, as this will change the blend mode after EACH instance is drawn, resulting in a draw call.
//original blendstateadditiveParticleEffect.draw(batch, delta); //set the blend state to additive, (flushes the batch)//additiveParticleEffect will then reset the batch to the original blend state (flushes the batch)//repeat//original blendstateadditiveParticleEffect.draw(batch, delta); //set the blend state to additive, (flushes the batch)//additiveParticleEffect will then reset the batch to the original blend state (flushes the batch)//repeat
setEmittersCleanUpBlendFunction function, and set it to false. This will prevent the ParticleEffect from resetting the blend mode to the original, and avoiding the extra flush of the Batch.
//original blendstateadditiveParticleEffect.draw(batch, delta); //set the blend state to additive, (flushes the batch)//blendstate is now additive//repeat//additive blendstateadditiveParticleEffect.draw(batch, delta); //already additive, no state change (no flush)//repeat
This is great, efficiently drawing lots of ParticleEffects with the same blend state! Be careful with this function, you are now in charge of returning the Batch’s blend state to the original, so you must do this after you are finished drawing all your particles.
Examples
Particle Park A coding example is available on LibGDX.info
Pooled effect example:
ParticleEffectPool bombEffectPool;Array<PooledEffect> effects = new Array();//...//Set up the particle effect that will act as the pool's templateParticleEffect bombEffect = new ParticleEffect();bombEffect.load(Gdx.files.internal("particles/bomb.p"), atlas);//If your particle effect includes additive or pre-multiplied particle emitters//you can turn off blend function clean-up to save a lot of draw calls, but//remember to switch the Batch back to GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA//before drawing "regular" sprites or your Stage.bombEffect.setEmittersCleanUpBlendFunction(false);bombEffectPool = new ParticleEffectPool(bombEffect, 1, 2);// Create effect:PooledEffect effect = bombEffectPool.obtain();effect.setPosition(x, y);effects.add(effect);// Update and draw effects:for (int i = effects.size - 1; i >= 0; i--) { PooledEffect effect = effects.get(i); effect.draw(batch, delta); if (effect.isComplete()) { effect.free(); effects.removeIndex(i); }}//...// Reset all effects:for (int i = effects.size - 1; i >= 0; i--) effects.get(i).free(); //free all the effects back to the pooleffects.clear(); //clear the current effects array
Batched effect example:
Array<PooledEffect> additiveEffects;Array<PooledEffect> normalEffects;ParticleEffect additiveEffect = new ParticleEffect();additiveEffect.load(//...);additiveEffect.setEmittersCleanUpBlendFunction(false); //Stop the additive effect restting the blend statebatch.begin();//draw all additive blended effectsfor (PooledEffect additiveEffect : additiveEffects) { additiveEffect.draw(batch, delta);}//We need to reset the batch to the original blend state as we have setEmittersCleanUpBlendFunction as false in additiveEffectbatch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);//draw all 'normal alpha' blended effectsfor (PooledEffect normalEffect : normalEffects) { normalEffect.draw(batch, delta);}batch.end();
video-example
- Particle Effect Example on LibGDX.info
- source of the video
- source of the video using pooling
