From 012f0b8a19f339a1500e4e9b734e5349f7ee81b3 Mon Sep 17 00:00:00 2001 From: tetrapod00 <145553014+tetrapod00@users.noreply.github.com> Date: Sat, 2 Nov 2024 22:22:29 -0700 Subject: [PATCH] Improve interpolation smoothing example Improves explanation of interpolation ("lerp") smoothing. Adds a note about framerate-independent version, with off-site links to full explanations. Co-Authored-By: aXu-AP <1621768+aXu-AP@users.noreply.github.com> --- tutorials/math/interpolation.rst | 51 ++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/tutorials/math/interpolation.rst b/tutorials/math/interpolation.rst index bddc26481..abc3f8434 100644 --- a/tutorials/math/interpolation.rst +++ b/tutorials/math/interpolation.rst @@ -3,7 +3,10 @@ Interpolation ============= -Interpolation is a very basic operation in graphics programming. It's good to become familiar with it in order to expand your horizons as a graphics developer. +Interpolation is a common operation in graphics programming, which is used to +blend or transition between two values. Interpolation can also be used to smooth +movement, rotation, etc. It's good to become familiar with it in order to expand +your horizons as a game developer. The basic idea is that you want to transition from A to B. A value ``t``, represents the states in-between. @@ -109,7 +112,11 @@ And again, it will produce the following motion: Smoothing motion ---------------- -Interpolation can be used to smooth movement, rotation, etc. Here is an example of a circle following the mouse using smoothed motion: +Interpolation can be used to smoothly follow a moving target value, such as a +position or a rotation. Each frame, ``lerp()`` moves the current value towards +the target value by a fixed percentage of the remaining difference between the values. +The current value will smoothly move towards the target, slowing down as it gets +closer. Here is an example of a circle following the mouse using interpolation smoothing: .. tabs:: .. code-tab:: gdscript GDScript @@ -138,4 +145,42 @@ Here is how it looks: .. image:: img/interpolation_follow.gif -This is useful for smoothing camera movement, allies following you (ensuring they stay within a certain range), and many other common game patterns. +This is useful for smoothing camera movement, for allies following the player +(ensuring they stay within a certain range), and for many other common game patterns. + +.. note:: + Despite using ``delta``, the formula used above is framerate-dependent, because + the ``weight`` parameter of ``lerp()`` represents a *percentage* of the remaining + difference in values, not an *absolute amount to change*. In ``_physics_process()``, + this is usually fine because physics is expected to maintain a constant framerate, + and therefore ``delta`` is expected to remain constant. + + For a framerate-independent version of interpolation smoothing that can also + be used in ``process()``, use the following formula instead: + + .. tabs:: + .. code-tab:: gdscript GDScript + + const FOLLOW_SPEED = 4.0 + + func _process(delta): + var mouse_pos = get_local_mouse_position() + var weight = 1 - exp(-FOLLOW_SPEED * delta) + $Sprite2D.position = $Sprite2D.position.lerp(mouse_pos, weight) + + .. code-tab:: csharp + + private const float FollowSpeed = 4.0f; + + public override void _Process(double delta) + { + Vector2 mousePos = GetLocalMousePosition(); + + Sprite2D sprite = GetNode("Sprite2D"); + float weight = 1f - Mathf.Exp(-FollowSpeed * (float)delta); + sprite.Position = sprite.Position.Lerp(mousePos, weight); + } + + Deriving this formula is beyond the scope of this page. For an explanation, + see `Improved Lerp Smoothing `__ + or watch `Lerp smoothing is broken `__.