playcanvas / engine

JavaScript game engine built on WebGL, WebGPU, WebXR and glTF
https://playcanvas.com
MIT License
9.5k stars 1.33k forks source link

Particle System simulation on 60Hz+ screens. #1721

Open Maksims opened 4 years ago

Maksims commented 4 years ago

There is a currently an issue, where simulating particles on screens with higher than 60Hz refresh rate, leads to particles to look too fast. So changingfixedTimeStep fixes an issue. But as I assume it has cost associated to it. For example if increasing it to lower number, like 1 / 240 for 240Hz screens, will have performance hit for 60Hz screens and mobile.

Could there be a global flag for it, and developer should manually decide somehow, what it to set to. There should be a solution to such problem, as monitors and mobile devices with 90, 144, 240, etc. are now becoming a common thing.

https://github.com/playcanvas/engine/blob/f1ae19316054c1bb88a38f9d44177133a14bade0/src/scene/particle-system/particle-emitter.js#L298

Maksims commented 4 years ago

I've ended up doing something like this: track average FPS over last 20 frames, if it is showing steady good FPS close to 90, then change fixedTimeStep on particles to 1 / 90. Then check to 120 then 144 and then 240. It progressively goes up. Averaging - is important, as random spikes in dt are common thing, so single frame time is not reliable.

Something without specific frames (60, 90, 120, 144, 240) steps, but threshold of 20%+ fps than previously steady one - could be good way of switching to better fixedTimeStep for particles. Can even start low, like from 30fps, this would provide better performance on weak devices.

slimbuck commented 4 years ago

Hey @Maksims,

That sounds like a cool solution. In general though changing simulation step time is actually dangerous as you may get subtly different results at different frame rates. Ideally the particle system would always run with a fixed frame step and then interpolate between two steps to match the current frame rate.

I am not familiar with the particle system implementation in playcanvas but I expect making it double buffer wouldn't be difficult (if it doesn't already). Perhaps it's something we can look to do in future.

noahcoetsee commented 4 years ago

I would definitely rather do some sort of hz detection, which is normally possible through other 3d engines (that are not on the web, such as DirectX and OpenGL).

Would it be possible to detect a machine's set HZ level or something like that?

mvaligursky commented 4 years ago

is there a strong reason to run it with a fixed time step instead of variable dt? Most fx system's I worked on / used were using variable dt without a problem.

Maksims commented 4 years ago

In general though changing simulation step time is actually dangerous as you may get subtly different results at different frame rates.

In this case, it is used like "minimum simulation step", and in a frame, it will perform at least one simulation tick. That is why current situation, on 240Hz screens, leads to 4x speedup of simulation. But setting fixedTimeStep to 1/240 (4.17ms), for 240Hz makes no difference in performance, as still performs single simulation tick, but on 60Hz screen, will have to perform 4 simulation ticks, to make up for 16.67ms.

Why it is a fixed simulation step, probably to avoid data interpolation and baking fixed step data into textures. Of course having variable dt and single simulation tick for GPU particles - would be way more desirable solution.

Summoning @guycalledfrank to ask: why GPU system uses fixedTimeStep solution instead of variable dt with interpolation solution?

mvaligursky commented 4 years ago

This is @guycalledfrank 's response we have

Screen Shot 2020-06-06 at 11 49 16 AM
mvaligursky commented 4 years ago

I'm not sure changing dt for fixed step should affect the speed of simulation .. only the precision / quality of it.

Maksims commented 4 years ago

I'm not sure changing dt for fixed step should affect the speed of simulation .. only the precision / quality of it.

Changing fixedTimeStep to larger number - will definitely lead to issue as described by Arthur above. But changing it to smaller number, will lead to higher precision, but also lower performance due to case where it will execute simulation step multiple times of fixedTimeStep is lower multiple times than dt.

mvaligursky commented 4 years ago

Agreed - all that is correct behavior, and changing dt should not change the the observed speed of the simulation, or even make duplicates of a single ParticleSystem run at different speed (current behavior observed on forum). Also keeping the default fixed dt of 1/60 should not make simulation to run faster on devices with higher refresh rate. That's something we need to investigate and try to understand and fix.