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

Use requestAnimationFrame timestamp for less noise in deltaTime #6785

Merged
merged 1 commit into from
May 28, 2024

Conversation

davepagurek
Copy link
Contributor

@davepagurek davepagurek commented Feb 1, 2024

Related to #5354 (but does not fully solve it)

Changes

This uses the timestamp passed into requestAnimationFrame callbacks instead of window.performance.now() if it's available.

This refers to the time when the browser starts calling callbacks, as opposed to the time the callback gets run. The rate between frames should be the same on average: this basically just offsets in time the point at which we measure, but not the time between samples.

The main difference is just that there's less noise in when the browser starts running RAF callbacks compared to when the browser actually runs each. This means that the variance in deltaTime goes down, and deltaTime values fluctuate less around their average. Previously, I was seeing a variance of around ~0.3, and after, I see a variance of around ~0.1.

Some implications:

  • If you're doing physics simulations with the step size based on deltaTime, your step size will be more consistent each frame.
  • Since the time the frame is actually drawn at still may vary, deltaTime may become slightly less accurate in measuring exactly how much time has elapsed since the last time draw was called, but more accurate in measuring the time between scheduled frame updates

So whether or not this is useful essentially boils down to whether or not we want frames to look like they're taking even steps even though they may not actually be drawn at quite so even steps. I think my gut feeling is that this actually produces perceptually smoother motion: at least personally, I perceive the time discrepancy less than the space discrepancy.

To compare:

Does this make sense to you all too?

PR Checklist

@davepagurek
Copy link
Contributor Author

Tagging the core/environment/rendering stewards. Let me know what you think! @limzykenneth, @ChihYungChang, @teragramgius, @tuminzee, @Zarkv, @robin-haxx, @Gaurav-1306

@limzykenneth
Copy link
Member

I thought of this before and the main thing I'm unsure about is how it behaves when the framerate is not 60 (or whatever the default framerate is) since they way we achieve that is through skipping frame being processed.

@davepagurek
Copy link
Contributor Author

davepagurek commented Feb 2, 2024

Here's a version of the test sketch that sets 23fps (try toggling the script tags in index.html to test 1.9.0, or changing the target frame rate in setup): https://editor.p5js.org/davepagurek/sketches/MC1mAZrba

The average fps looks the same to me, and I think that's because the timestamp we were previously using is kind of the same as this one, just with a few ms/μs offset, since previously it was recording when the callback gets run rather than when the browser starts queuing up the callbacks to run. I think since this offset is relatively consistent, but just with extra noise due to scheduling, which you can see in the reduced variance between deltaTime values while the average fps is still the same.

@limzykenneth
Copy link
Member

Ok, it seems the value roughly matches existing behaviour so I'm fine with this. The only thing left is the detail around rounding, with our current implementation we are getting whole numbers from deltaTime but with the requestAnimationFrame based value, we are getting more precise floats. Should we round this value to match existing behaviour?

@davepagurek
Copy link
Contributor Author

Do you think anything relies on it being a whole number? My initial inclination is to say that it probably doesn't matter (unlike frameCount, I doubt anyone uses === to compare with deltaTime because of the noisiness) but I haven't thought through yet whether or not there would be other cases where it would make a difference. Maybe just if people print it directly for debugging?

@limzykenneth
Copy link
Member

limzykenneth commented Mar 1, 2024

It's probably a bit hard to say. For people printing or drawing the value on canvas, this will likely be a bit of a problem but should be solveable easily. For people relying on its value for animation, it can possibly cause subpixel drawing to happen more often and may be undesirerable but I'm not sure if it really is an issue.

@davepagurek
Copy link
Contributor Author

I think for subpixel drawing, users probably already need to be calling round() manually when converting the values into coordinates, unless they are using the deltaTime values directly without multiplying or dividing, which seems like a fairly small use case. So in that case, this change would likely not affect many users.

@limzykenneth limzykenneth merged commit 40ff3f9 into processing:main May 28, 2024
2 checks passed
@davepagurek davepagurek deleted the deltatime-variance branch May 28, 2024 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants