Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Bug / Crash  Fluid emitter stuttering with more fixed steps and lower FPS
#1
Before I get into my problem, I just wanted to say how amazing the new version of Obi is. Thank you so much for continuing to work on these tools, the new Compute solver is incredible  and the new fluid surface mesher is pure magic. We've been able to vastly increase fluid particle numbers and visual fidelity while also massively improving performance. The main issues I've had are just getting any kind of colour and opacity out of liquids, but I've been able to tweak the shaders in shadergraph to solve that and add custom effects. Honestly, you've done some amazing work on these tools!

The problem:

The issue I'm having now is with the simulation speed and emitter particle speed in a game that runs under the fixed timestep. We're using a fixed timestep of 0.1666667 and all the sample scenes work perfectly fine because they all run above 60 FPS, but in our actual game scene our FPS often dips under 60. This causes the simulation to appear to run in slow motion because the Obi Solver is running 1 max step per frame.

When I increase the max steps per frame, the simulation appears to run at full speed because it's doing the extra catch-up steps when needed, the new docs pages about the simulation timesteps has been very useful in figuring that out. The issue is that in this circumstance, the Obi Emitters no longer emit a steady stream, the stream becomes broken up with gaps, where some frames produce more particles and some less.

There's also a visible gap at the point of fluid emission that gets worse with increased fixed steps per frame because the simulation has already moved the particles by the time the next render frame comes around. It seems that emitted particles don't get rendered until they've been through a full simulation cycle and at that point they aren't at the location they spawned in. I would have expected that emitted particles would be rendered immediately so that the precise emitter particle spawn spots are always filled and the fluid always appears to start solidly from the same location.

Possible cause and workaround:

I think the cause has to do with an instability in the number of fixed frames per rendered frame, where some rendered frames end up with 1 fixed frame and some have 2, or if you're below half the fixed timestep some will have 2 and some will have 3. Emitters can only emit particles in discrete quantities, so that naturally results in stuttering. The frames that have 3 fixed updates move the existing particles further and the ones with 2 fixed updates don't move them far enough to cause new particles to be emitted, so that leads to gaps.

Ultimately I do have to try to get the performance of the scene up, but the only solution I can think of for anyone below 60 FPS would be to forcibly lock the framerate to integer factors of the fixed timestep. So any frame rate under 60 would become 30 so it'd always be precisely 2 fixed steps per frame, and then anything below 30 would become 15. That's not ideal but it does stabilise the simulation speed as too few fixed update steps leads to slow simulation and inconsistent numbers of steps leads to gaps.

The alternative would be to use a script to dynamically set the max steps per frame depending on the frame rate so that it never goes too high. For example, a game running at 50FPS would have a max steps of 1 and the simulation would just appear to run slightly slowly, while at 25 FPS the game would have a max steps of 2 and again just appear to run slightly slowly. That might be preferable to locking the frame rate, it's a trade-off I might have to make.

Remaining questions:

Writing this out has helped me figure it out, but does this all sound right to you or could there be a bug with how emitters handle different numbers of fixed timesteps? Also particles emitted seem to undergo a full frame's simulation cycle before they're rendered, causing that visible gap at the point of emission if there's a lot of sim steps per frame occurring, is that something that you could change or is it not possible to render emitted particles until they've gone through a simulation step?


Once again, amazing toolset Jose!
Reply
#2
Hi Nyphur!

Thanks for your kind words, they're really appreciated Sonrisa.

(20-09-2024, 01:52 PM)Nyphur Wrote: There's a visible gap at the point of fluid emission that gets worse with increased fixed steps per frame because the simulation has already moved the particles by the time the next render frame comes around. It seems that emitted particles don't get rendered until they've been through a full simulation cycle and at that point they aren't at the location they spawned in. I would have expected that emitted particles would be rendered immediately so that the precise emitter particle spawn spots are always filled and the fluid always appears to start solidly from the same location.

Also particles emitted seem to undergo a full frame's simulation cycle before they're rendered, causing that visible gap at the point of emission if there's a lot of sim steps per frame occurring, is that something that you could change or is it not possible to render emitted particles until they've gone through a simulation step?

The exact point at which simulation and rendering happen depend on the solver's synchronization mode. By default, Obi uses asynchronous mode which renders the previous frame, then kicks off simulation of the current frame. This allows an entire frame worth of time for the simulation to be completed before the main thread has to wait for its results, which yields the best performance. However, rendering is always 1 frame behing physics state. Check the new page for update loop / timesteps as it also explains this: http://obi.virtualmethodstudio.com/manua...eloop.html

You can switch to synchronous mode. This is considerably costlier as it forces the frame's simulation to finish before rendering, but the current frame's state is rendered instead of the previous one.

(20-09-2024, 01:52 PM)Nyphur Wrote: Possible cause and workaround:

I think the cause has to do with an instability in the number of fixed frames per rendered frame, where some rendered frames end up with 1 fixed frame and some have 2, or if you're below half the fixed timestep some will have 2 and some will have 3. Emitters can only emit particles in discrete quantities, so that naturally results in stuttering. The frames that have 3 fixed updates move the existing particles further and the ones with 2 fixed updates don't move them far enough to cause new particles to be emitted, so that leads to gaps.

That's not entirely accurate: the amount of particles emitted per frame depends on the ratio between the velocity of the emitted particles and their size: at the start of each step the distance the previously emitted particles have moved forward is calculated and divided by the size of a particle, this yields the amount of particle "bursts" that need to be emitted and the distance from the emitter that they should be spawned at.

So the distance between particles should be constant regardless of the amount of time steps performed during the frame. Will test this and get back to you, if it doesn't work as expected there might be a bug.

kind regards,
Reply
#3
Just set up a quick test: set Unity's fixed delta time to 0.005 in order to force multiple timesteps per frame, set the solver's max steps per frame to 4. However no gaps appear in between emitted particles, flow seems continuous.

Also tried the opposite: set the fixed delta to 0.3, to force frames where no timesteps take place. No gaps either - although particles are able to travel a significant distance from the emitter before new particles are emitted to fill the void, so that might count as a gap. Can't do anything in this case since the emitter has no chance to emit new particles until at least 0.3 seconds have passed since last emission, however it emits more particles to compensate.

Would it be possible for you to set up a scene that reproduces the issues you mentioned? I'll be glad to take a look at it.

kind regards,
Reply
#4
(23-09-2024, 11:39 AM)josemendez Wrote: That's not entirely accurate: the amount of particles emitted per frame depends on the ratio between the velocity of the emitted particles and their size: at the start of each step the distance the previously emitted particles have moved forward is calculated and divided by the size of a particle, this yields the amount of particle "bursts" that need to be emitted and the distance from the emitter that they should be spawned at.

So the distance between particles should be constant regardless of the amount of time steps performed during the frame.

That was my understanding as well, but I've observed that it's not the case. It seems to be that if you have irregular numbers of fixed timesteps happening per rendered frame, the particle emission becomes unstable and the stream breaks up. It shouldn't logically happen, but it's happening consistently and makes me think there's potentially a bug in the emitter code.

(23-09-2024, 11:50 AM)josemendez Wrote: Just set up a quick test: set Unity's fixed delta time to 0.005 in order to force multiple timesteps per frame, set the solver's max steps per frame to 4. However no gaps appear in between emitted particles, flow seems continuous.
Would it be possible for you to set up a scene that reproduces the issues you mentioned? I'll be glad to take a look at it.

Sure, I'll get some time to put together minimum viable reproduction scenes of these issues at some point and send them over.

To be clear though, these issues are not caused by there being multiple fixed timesteps per frame so just changing unity's timestep and the solver's max steps won't show this bug. These bugs seem to be explicitly happening when there's a non-integer ratio of rendered frames to fixed frames so that some rendered frames get more fixed frames than others. For example, if you had say 28 FPS and a fixed timestep of 1/50 you'd see the bug, but at 25 FPS it would disappear because that's an integer factor of 50.

The bug will only show up in a scene with sufficient rendering load to reduce the rendered FPS below the fixed timestep, so it may not easily show up in your minimalist test scenes but will happen in a real game fairly easily. Put a few hundred complex skinned meshes in camera view to artificially bring your FPS down and you may see the issue. I'll try to get the time to put together a test scene/project showing it.
Reply