Framerate Independent Interpolation

Yesterday I watched Freya's new video about lerp smoothing and it reminded me of the damping implementation of Cinemachine to control camera motion smoothly. In this blog post, I will give you more perspectives to understand the framerate-independent interpolation other than the ones deduced from Freya's video.

Frame-Dependent Interpolation

Let's first recap the frame-dependent interpolation. Let be the source position, the target position, and is a fixed value representing the ratio will go through towards , and be the current position after iterations (frames). The update equation is:

with being the original source position. We can recursively expand this equation:

It is obvious that is dependent on , which generally represents the frames per second (FPS). and produce significantly different results.

Frame-Independent Interpolation

The naive interpolation is frame-dependent because it's updated based on the unit of frames, rather than seconds. We would like the interpolation function , if is generalized to , is only dependent on the elapsed time rather than the frame rate.

Freya has given an interpretation to solve in her video. In the following sections I will give three more perspectives of understanding and solving .

Perspective #1: Solving the Function Equation

What we need is: for any and any , the following equation holds:

This equation means that at any timestamp , no matter how many pieces we segment into, the accumulated interpolation result is always equal to the one without segmentation. is the number of segments and is applying sequentially times.

We can derive explicitly:

Having it equal to :

Let's prove that must be an exponential function, assuming .

First, we rewrite the above funciton equation to:

This means that the original equation also holds for .

We also have:

This means that the original equation also holds for . We can prove it further holds for by leveraging the property that is continuous. In , we take and get:

is therefore an exponential function subtracted by , which can be represented by . Substituting this form into :

and this is why we choose a negative power: we would like to value to lie within . At each frame, we update the value of using where is elapsed time during this frame. As long as the FPS is stable, the result is definitely frame-independent.

Perspective #2: Solving the Differential Equation

From another perspective, we can view as a function of , i.e., where is the initial value. For any we can compute its value at :

which can be simplified to:

Solving this differential equation we have where is to be determined. Substituting we solve . Hence the final equation for is where . This aligns with the result from the first perspective.

Perspective #3: Rewriting the Naive Lerp

Actually, we can even produce the same result of from the naive interpolation formula. Starting from the naive update equation for the -th frame:

assuming is the frames per second, e.g., , or . It should be particularly noticed that the unit of is percent per frame, or . We would like to transform the unit of to percent per second, or representing how many percentages will go through towards per second rather than per frame. To this end, we need to first view in the unit of and multiply it with some value with unit so that it can be used at each frame to update the input value.

The question is, what value has the unit . Recall that the unit of is , and its inverse, which represents the elapsed time per frame, has unit . Therefore, we just need to multiply with the inverse of , and this becomes:

where has unit instead of . Well, will definitely remind you of the following limit:

If we take limits for , the update equation now will be:

Note that the is the update formula for one second. For one frame, we need to multiply with , the elapsed time per frame:

This is exactly what we've derived from the second perspective!

You may wonder why you cannot directly use as the update formula, i.e. . Of course you can do this! It's much simpler and is more performant (not involving the exponential function), and it's a pretty good approximation to . But if you want a more accurate frame-independent interpolation formula, you should use the version.

Conclusion

In this short post, I introduced three perspectives to understand the frame-independent interpolation. Don't get stuck with the details, just use the very neat and clean form of interpolation: the exponential function. If you want to know what we can do to mitigate when FPS is unstable, you can read this post. Thanks for reading!