Logarithmic Interpolation

April 19, 2018
protect

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)

<iframe title="Logarithmic Interpolation" src="//www.youtube.com/embed/u1A_6Ap4xmE?enablejsapi=1&amp;origin=https%3A%2F%2Fwww.gamedeveloper.com" height="360px" width="100%" data-testid="iframe" loading="lazy" scrolling="auto" class="optanon-category-C0004 ot-vscat-C0004 " data-gtm-yt-inspected-91172384_163="true" id="617903879" data-gtm-yt-inspected-91172384_165="true" data-gtm-yt-inspected-113="true"></iframe>

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.

<iframe title="Solaro Seamless Target View" src="//www.youtube.com/embed/mp5qHjm9i20?start=18&amp;enablejsapi=1&amp;origin=https%3A%2F%2Fwww.gamedeveloper.com" height="360px" width="100%" data-testid="iframe" loading="lazy" scrolling="auto" data-gtm-yt-inspected-91172384_163="true" id="120736825" class="optanon-category-C0004 ot-vscat-C0004 " data-gtm-yt-inspected-91172384_165="true" data-gtm-yt-inspected-113="true"></iframe>

Cheers, and happy zooming!

 

JikGuard.com, a high-tech security service provider focusing on game protection and anti-cheat, is committed to helping game companies solve the problem of cheats and hacks, and providing deeply integrated encryption protection solutions for games.

Read More>>