Gamasutra: The Art & Business of Making Gamesspacer
arrowPress Releases
  • Editor-In-Chief:
    Kris Graft
  • Editor:
    Alex Wawro
  • Contributors:
    Chris Kerr
    Alissa McAloon
    Emma Kidwell
    Bryant Francis
    Katherine Cross
  • Advertising:
    Libby Kruse






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

NEXON M
NEXON M — Emeryville, California, United States
[11.14.18]

Software Engineer
NEXON M
NEXON M — Emeryville, CA, California, United States
[11.14.18]

Data Engineer
Tender Claws
Tender Claws — Los Angeles, California, United States
[11.14.18]

Senior Unity developer
Wargaming.net
Wargaming.net — Chicago, Illinois, United States
[11.14.18]

Senior UI Engineer





Loading Comments

loader image