Gamasutra: The Art & Business of Making Gamesspacer
View All     RSS
February 16, 2019
arrowPress Releases

If you enjoy reading this site, you might also want to check out these UBM Tech sites:


Logarithmic Interpolation

by Scott Lembcke on 04/18/18 04:19:00 pm   Featured Blogs

The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.


Linear interpolation is incredibly useful, but sometime values are better expressed on a logarithmic scale. A good example is zooming in with a camera. Say you zoom in by 2x, then zoom in by 2x again, then once more. Visually you want to treat all of these zoom changes the same even though the last one is a change from 4x - 8x compared to the original zoom amount. While the following code will work, it won't quite look right. The lower the zoom is, the faster the zoom rate will change. If you need some Google Earth style 100,000:1 zooming, it will definitely look wrong!

// Not-quite-constant rate zooming. :(
zoom = lerp(zoom, targetZoom, deltaTime/duration)

Compare the two sides. Notice how the left side seems to speed up and slow down even though it starts and ends on the correct zoom level. That's what regular linear interpolation looks like for the camera zoom. The right side keeps the same zoom speed the whole time. So how do you do that?

What you want to do, is convert the zoom values to a logarithmic scale, then convert them back to linear afterwards. No matter what your endpoints are, the zooming will always look smooth.

// Constant rate zooming!
zoom = exp(lerp(log(zoom), log(targetZoom), deltaTime/duration)

If you dust off that old sheet of power rules from your algebra class, you can simplify it a bit to this:

// Slightly simpler constant rate zooming!
zoom = zoom*pow(targetZoom/zoom, deltaTime/duration)

// ..or as a function:
float logerp(float a, float b, float t){
  return a*pow(b/a, t);

If your camera's zoom is always changing to meet a target zoom level, you can combine it with the lerp() smoothing trick I posted about a few days ago. We did this in an old space game that we worked on to make the zooming extra smooth.

Cheers, and happy zooming!


Related Jobs

Boston Dynamics
Boston Dynamics — Waltham, Massachusetts, United States

Software Engineer
Wargaming Sydney
Wargaming Sydney — Broadway, New South Wales, Australia

Gameplay Programmer, C++ - Vehicle Physics
Skydance Interactive
Skydance Interactive — Marina Del Rey, California, United States

Lead Engineer
The Behemoth
The Behemoth — San Diego, California, United States

Experienced Network Programmer

Loading Comments

loader image