Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Particles: can't control actual emission rate (trying to do so through "lifetime" is prone to misbehavior) #26963

Closed
aqnuep opened this issue Mar 12, 2019 · 8 comments

Comments

@aqnuep
Copy link
Contributor

aqnuep commented Mar 12, 2019

Godot version:
Master 75c89aa

OS/device including version:
Win7 / Radeon 7870

Issue description:
Particles cause quite a bit of a dip in frame rate when emitting, but the problem is that even after they are stopped the frame rate doesn't go back up to to rate before emission has been started.
Deleting the entire Particles node after stopping it does restore the frame rate so I suspect that some of the processing continues to happen even after the emitter has been stopped and there are no more visible particles.

Steps to reproduce:

  1. Create a Particles node with emitting=false
  2. Observe frame rate
  3. Set emitting=true (e.g from script)
  4. Observe frame rate getting lower
  5. Set emitting=false (e.g. from script) and wait until all particles complete their lifetime
  6. Observe frame rate getting higher, but not as high as it was at (2)

Edit: The issue only happens if the script manipulates the lifetime property while the emitter is active, see #26963 (comment) below.

Minimal reproduction project:
Should be trivial to reproduce.

@abhinavsagar
Copy link

@aqnuep I think that's a problem with your system. I just reproduced it on my local machine and it's working absolutely fine. @akien-mga Please review this.

@eon-s
Copy link
Contributor

eon-s commented Mar 12, 2019

The version is 20 days old and there were some changes on particles and materials, can you try a more recent build?

@aqnuep
Copy link
Contributor Author

aqnuep commented Mar 12, 2019

@aqnuep I think that's a problem with your system. I just reproduced it on my local machine and it's working absolutely fine. @akien-mga Please review this.

I'm really curious to hear what in my "system" could cause a lower frame rate when setting emitting=false vs when also deleting the entire node after it... (both should stop updates of the particles)

The version is 20 days old and there were some changes on particles and materials, can you try a more recent build?

Tested it with latest master, plus also with both "release_debug" (editor) and "release" (export) builds, but the issue persists.

Looks like the transform feedback particle processor shader is not stopped from continuing to execute even after emitting is disabled and pending particles have come to the end of their lifetime (confirmed with RenderDoc).

@aqnuep
Copy link
Contributor Author

aqnuep commented Mar 12, 2019

Okay, so I went a bit further and dug up the conditions used by the engine to stop continuing to update the particles and I found this:

if (particles->inactive_time > particles->lifetime * 1.2)

Which is not too surprising (except for the magic constant 1.2 which really should probably be something like 1 + EPSILON), but that made me realize the repro instructions I've provided are not entirely complete.

Thing is, in the test I conducted I needed control over the emission rate in some way and due to lack of direct support (see #4294), I achieved that effect by manipulating lifetime over time (as really emission rate is amount / lifetime and unfortunately, changing amount resets the particles).

However, it looks like even though that's possible to do, it doesn't interact well with the engine's way of deciding when a particle emitter became inactive and thus does not need further processing.

Messing around with the value of lifetime after emitting is disabled and setting it to a value to help satisfy the inactive condition did allow the frame rate to get back up (and no longer issue any more particle process shaders).

Now the question is what is the intended behavior here. Is the engine supposed to allow manipulating the lifetime property while the emitter is active? If not, maybe it should generate an error. If yes, then maybe there's a need for a better way to detect inactivity.

Not sure about the answer and I'm fine if this is not considered a bug after all, but this may cause suprises to other users trying to achieve similar effects like I did.

@clayjohn
Copy link
Member

Emitting just determines how long particles will be emitted. It has no bearing on when a particle updates. The expected behaviour is that a particle updates for its entire lifetime after having been emitted.

If you want to change the rate of emission within the liftetime you should use the explosiveness property.

The expected behaviour is that a particle will update for its lifetime.

It does seem that there is some issues around setting the lifetime of particles that have been emitted. It sounds like there may be a bug in there somewhere, i would expect that lifetime could be updated anytime and it would affect the life of the particles without issue.

@aqnuep
Copy link
Contributor Author

aqnuep commented Mar 12, 2019

Emitting just determines how long particles will be emitted. It has no bearing on when a particle updates.

Of course it has. Updating happens as long as there are live particles which happens while emitting is active or for lifetime amount of time after emitting has stopped.

If you want to change the rate of emission within the liftetime you should use the explosiveness property.

That's not exactly what explosiveness is about. Explosiveness only controls the distribution of emissions across the lifetime, but the actual emission rate over the course of amount number of particles emitted implicitly equals amount / lifetime. You can't really use explosiveness to control the exact N particles / second rate of emission, while you more or less can do so by adjusting lifetime (as mentioned above).

The root of the problem I encountered is that even though you can change the various parameters of the emitter, really some of them are sort of assumed to be immutable, as other logic depends on it, like it's the case with the inactive detection (which stops further updates), that depends on the current value of lifetime to determine when the emitter is inactive thus requires no updates, and that can cause some (at least somewhat) unexpected side effects, e.g.:

  • If you suddenly change lifetime to a smaller value when you stop the emitter, then the already alive particles will die earlier than expected, according to the current value of lifetime, even though when they were emitted the lifetime was larger, so they no longer get updated or rendered
  • Similarly, if you suddenly change lifetime to a larger value when you stop the emitter, then the already alive particles will be considered alive for a much longer time than the lifetime they were created with, thus they continue to get updated even if they may be no longer visible (this is what happened in my case)

Anyway, adjusting the lifetime property appropriately when stopping the emitter solved my problem, though my (arguably) abuse of the lifetime property to actually control emission rate fairly accurately, even if achieves the same effect in practice, is not really a great solution. Though we discussed this topic with @reduz so I don't want to rehash that.

@clayjohn
Copy link
Member

I think we are actually in agreement here.

The issue you are currently experiencing is a result of expected behaviour that resulted in unexpected results when you tried to get the particles to do something it wasn't made to do. It is expected behaviour that the particles lifetime would adjust when you change the lifetime parameter. It is unexpected for you because you thought that lifetime was stored per-particle. That in itself is not a bug. But it sounds like you've figured that out all on your own.

The core of the issue here is that there should be some way to control particle emission based purely on emission rate. I agree with that. It would be great if you would change the title of the issue to reflect the fact that we need to add an emission_rate property. That way it will be easier for contributors to spot the suggestion and implement it. Thanks!

@aqnuep aqnuep changed the title GPU particles cause permanent FPS drop even after stopped Particles: can't control actual emission rate (trying to do so through "lifetime" is prone for misbehavior) Mar 13, 2019
@aqnuep aqnuep changed the title Particles: can't control actual emission rate (trying to do so through "lifetime" is prone for misbehavior) Particles: can't control actual emission rate (trying to do so through "lifetime" is prone to misbehavior) Mar 13, 2019
@akien-mga akien-mga added this to the 4.0 milestone Jun 24, 2020
@clayjohn
Copy link
Member

This bug report is a feature proposal on disguise.

It is essentially proposing that we add an emission_rate property instead of the current lifetime-based system.

As a particles feature request, it should be tracked here godotengine/godot-proposals#815 as all feature requests need to go through the proposals process.

@clayjohn clayjohn removed this from the 4.0 milestone Jun 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants