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

Incorrect lerp usage with deltatime for camera smoothing (and probably other things too) #93115

Open
mse-k opened this issue Jun 13, 2024 · 5 comments

Comments

@mse-k
Copy link

mse-k commented Jun 13, 2024

Tested versions

  • Issue was checked for and is present in all the recent major release branches (master, 3.x, 3.5, and 4.2)

System information

N/A

Issue description

The function that interpolates the camera position to the position it should be following isnt properly calculated with the frame delta, causing any usage of camera smoothing to be frame rate dependent (and more jittery that it needs to be!). Currently it calculates the % to move by multiplying the delta time and the smoothing speed, but this is easily seen to be wrong; imagine if the delta time was >1, that would mean the camera would go all the way over its target, which should not be possible at all! The correct way to do this is using an exponential function, which adds up correctly over different frame rates and will never go above 1. Something like

			real_t c = 1 - pow(0.7, position_smoothing_speed * delta);
			smoothed_camera_pos = ((camera_pos - smoothed_camera_pos) * c) + smoothed_camera_pos;

would fix the issue, 0.7 can be any number between 0 and 1 though.

Steps to reproduce

Compare the motion of the camera between two different fpses (say, 15 and 120) and notice how even if they have the same speed, they move completely differently.

Minimal reproduction project (MRP)

N/A (i based this issue on the c++ code, not actually making it in a project)

@Calinou
Copy link
Member

Calinou commented Jun 13, 2024

@clayjohn
Copy link
Member

CC @lawnjelly @rburing

@F3der1co
Copy link

F3der1co commented Jun 13, 2024

Also see Freya Holmérs talk on this topic https://youtu.be/LSNQuFEDOyQ?si=gBw9Sx5xxtMr_WVZ&t=2990 , there she suggest using an exponential decay function for smoothing lerps, which is much faster to calculate as it omits the pow()
image

@MrEgggga
Copy link

MrEgggga commented Jun 22, 2024

This has come up in a game i'm working on -- the camera lurches forward a bit every time a frame takes too long.

Here's a somewhat-minimal reproduction project. The square here is in free fall, with the camera following behind it. Every frame there is a 1% chance to do some slow calculation -- when this happens the camera gets significantly closer to the square (& sometimes ahead) when it should be staying behind. (The computation might not be slow enough to make a noticeable difference for people with fast computers.)

minimal_reproduction.zip

@MrEgggga
Copy link

MrEgggga commented Jun 22, 2024

I think this would work -- essentially the same as what mse-k suggested in the original message but with exp instead of pow w/ base of 0.7:

			real_t c = 1 - exp(-position_smoothing_speed * delta);
			smoothed_camera_pos = ((camera_pos - smoothed_camera_pos) * c) + smoothed_camera_pos;

With this, the camera will move the same as before (but framerate-independent) for the same position_smoothing_speed.

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

5 participants