Trending
Opinion: How will Project 2025 impact game developers?
The Heritage Foundation's manifesto for the possible next administration could do great harm to many, including large portions of the game development community.
Featured Blog | This community-written post highlights the best of what the game industry has to offer. Read more like it on the Game Developer Blogs or learn how to Submit Your Own Blog Post
Linear interpolation is undeniably useful, but sometimes values are better expressed on a logarithmic scale (music notes, zoom factors), and logarithmic interpolation is a better fit.
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!
Read more about:
Featured BlogsYou May Also Like