Jump to content

WHY are particle emitters so hard on performance?


valueerror
 Share

Recommended Posts

so pixi's bunnymark can render 10000 Bunnies whithout losing one single frame per second on my testing devices...

 

this particle emitter costs me 10-20 fps (tested on a oneplus one and on a slower desktop pc) !!!!

snowemitter2 = game.add.emitter(game.world.centerX, worldheight+40, 100);          snowemitter2.makeParticles(['snow1','snow2','snow3','snow4','snow6','snow7']);//snowemitter2.setAlpha(1, 0.5,5000,Phaser.Easing.Quintic.Out);//snowemitter2.setScale(1.5, 0.5, 1, 0.5, 3000, Phaser.Easing.Quadratic.InOut,true);snowemitter2.setSize(200, 0)snowemitter2.gravity = 300;snowemitter2.minParticleSpeed.set(-100, -50);snowemitter2.maxParticleSpeed.set(100, -200);snowemitter2.setRotation(-30, 30) // start(explode, lifespan, frequency, quantity, forceQuantity)         snowemitter2.start(false, 2000, 30);

please ..  can someone tell my why this is happening..

i already saw in my last game that exploding 10 particles produces a noticable framedrop so i had to reduce it to 4 (still costs 2-5 fps)

 

this is certanly not good..  is there some explanation or something i can do about it? 

Link to comment
Share on other sites

reducing the particle flow from releasing a particle on almost every frame to releasing a particle only every 6th frame (ever 100ms) reduced the framedrops dramatically...

 

i want to create an avalanche and reducing the number of particles also reduces the quality of the effect but resizing the particles to 200% helped to improve it again :)

 

still the question remains..  why is it so hard to render those particles when it's obviously no problem to render 10000 simple sprites

Link to comment
Share on other sites

Depending on the order that the Pixi renderer handles textures, it may be very though on performance. It will either use the depth buffer and render all objects with the same texture and shader at the same time, or simply render everything in order, so if these snow particles are stacked on top of each other in random order the number of texture switches may be increased by a ton. Try changing 

 

"snowemitter2.makeParticles(['snow1','snow2','snow3','snow4','snow6','snow7']);"

 

to 

 

"snowemitter2.makeParticles(['snow1']);"

 

and look for any performance changes.

 

I doubt it will work, but it's worth a shot. If it does work, it talks pretty poorly about Pixi.

Link to comment
Share on other sites

i'm using separate sprites for now because i'm just testing..   definitely using an atlas in the final version..

 

pixi (at least in it's bunnymark) http://www.goodboydigital.com/pixijs/bunnymark/  renders 10 000 frames per second without any problems..  so it's not the simple rendering that is causing problems..  probably the constant killing an reviving?  i haven't  profiled my "avalanche" jet..  probably a memory issue.. i don't know..  but i know that the particle system has been the reason for many performance issues here in this forum  :(

 

i tried using only one sprite instead of 6..  nothing changed..  the only thing that helps is keeping the number of spawned sprites very very low :(

Link to comment
Share on other sites

Under webGL using even a few separate sprites created a massive slow down compared to a sheet for me. Have you tried forcing to canvas to see if that is better - just for testing to see why not necessarily for final build.

Edit: sorry I just saw you tried switching to a single sprite so this is probably not worth trying.

Link to comment
Share on other sites

i tested the same setup with 10 individual tweened images and it was much better performancewise..  now i'm confused :)

 

it's not as dynamic and good looking as before but i will do the trick..  62fps on the oneplus and the moment another particle emitter explodes 8 images the fps drop to 50 - hey rich - if you read this..  could you shed some light on this ? THX !

Link to comment
Share on other sites

I also thought particles were more expensive than they should be.  I know you can't compare batched bunnies against anything other than... batched bunnies, but in my experience the pixels being pushed from a handful of particles were much much less than the overall number and size and texture swaps going on elsewhere, but critically, small adjustments to number of particles were giving a noticeable performance drop.

 

My particles were using blendmode ADD in canvas mode, maybe that's the expensive reason?  I did mean to investigate further at a convenient point in time, but in the meantime settled to just reduce number of particles.

Link to comment
Share on other sites

  • 2 weeks later...

I'm experiencing the same issue: my fps drops from 60+ to about 30 with three particle emitter pumping particles at a frequency of 200 (default is 250). I'm testing on a Windows Phone, re-building and deploying through Visual Studio every time, so the cache can't be the issue. Bunnymark also runs at a solid 60 fps on my phone with up to 5000 bunnies on screen so drawing is not the issue.

 

I suppose you could tween individual sprites, but then you're basically writing your own particle emitter function and that's just silly.

 

I'd really appreciate a comment from Rich on this!

Link to comment
Share on other sites

  • 5 months later...

Ouch. Yeah, I can only have maybe 10-20 emitters before things start to slow down. The number of emitters effects performance much more-so than the particle rate. Anyone have any ideas as to improve performance for emitters?

 

In my case, all my emitters are emitting the same exact thing. They're just displayed in different places on the map. I wonder if I could use a render texture for the duplicate emitters rather than creating a new emitter each time? Maybe stopping/starting the emitter when it leaves/enters the camera view?

Link to comment
Share on other sites

Folks, I've figured it out. At least for what I want to do which is:

 

A) Lots of particle emitters but not all necessarily rendering on the screen at the same time

B ) All the particle emitters are the same (fires in my case)

 

I can have hundreds of emitters on the map without a drop in performance if I use render textures that don't update unless the sprites they are textures of are in camera (see edit #2 below). Here's my code. Note that fireRenderTexture, smokeEmitter and fireEmitter are global variables. fireUpdate is placed in the game loop and startFire called in create or while the game is running (obviously). This is just my first pass so I'm sure I'll be able to optimize this in the future.

 

function startFire(emitX, emitY, scale) {    if (fireRenderTexture == undefined) {        smokeEmitter = game.add.emitter(emitX, emitY - 15, 50);        smokeEmitter.makeParticles(['smoke-puff']);        smokeEmitter.gravity = -300;        smokeEmitter.setAlpha(.7, 0, 3000);        smokeEmitter.setScale(scale, 0, scale, 0, 3000);        smokeEmitter.minRotation = 0;        smokeEmitter.maxRotation = 0;        smokeEmitter.start(false, 1000, 30);        fireEmitter = game.add.emitter(emitX, emitY, 50);        fireEmitter.makeParticles(['fire1', 'fire2', 'fire3']);        fireEmitter.gravity = -2000;        fireEmitter.setAlpha(.4, 0, 800);        fireEmitter.setScale(scale, 0, scale, 0, 3000);        fireEmitter.minRotation = 0;        fireEmitter.maxRotation = 0;        fireEmitter.start(false, 1000, 30);        fireRenderTexture = game.add.renderTexture(600, 600);    } else {        var fire = game.add.sprite(600, 600, fireRenderTexture);        fire.scale.set(scale);         fire.anchor.set(.5);        fire.x = emitX;        fire.y = emitY;    }}function updateFire() {    fireRenderTexture.renderXY(smokeEmitter, 0, 0, true);    fireRenderTexture.renderXY(fireEmitter, 0, 0, false);}

78kxjci.gif

 

About the game I'm working on: feudalwars.net

 

Edit:

 

Reduce the number of particles of 10-20 and their life time and frequency decreases. Be happy

 

 

That helps too. In my case, I had way too many particles (400). I turned it down to 50 and it dramatically improved performance:

smokeEmitter = game.add.emitter(emitX, emitY - 15, 50);
And lower the lifespan (from 3000 to 1000):
smokeEmitter.start(false, 1000, 30);

(did the same to fire emitter). 

 

It looks about the same but is much better on performance. Still need to use the renderTexture trick (above) though as that is 1000x better on performance when there are a lot of emitters on the map. 

 

Edit #3:

Okay, creating a new renderTexture each time (and updating it when in camera) is asinine and I realized that... instead, create a single render texture and set the texture of new sprites to that single render texture. With the code above, the first one that you create should probably be full size (scale of 1) just so your render texture sprites up/down from the original dimensions rather than scaled dimensions.  

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...