Up to date
This page is up to date for Godot 4.3.
If you still find outdated information, please open an issue.
插值
插值是图形编程中一个非常基本的操作. 作为一名图形开发人员, 熟悉它有助于扩展你的视野.
基本思想是从 A 转换到 B。t 值是介于两者之间的状态。
举个例子,如果 t 是 0,那么他的状态是 A。如果 t 是 1,那么它的状态是 B。任何介于两者之间的状态都是插值。
两个实数(浮点数)之间的插值可以描述为:
interpolation = A * (1 - t) + B * t
通常简化为:
interpolation = A + (B - A) * t
这种以恒定速度将一个值转换为另一个值的插值被称为“线性”。因此,当你听到线性插值时,你就知道他们指的是这个公式。
还有其他类型的插值, 这里将不做讨论. 建议之后阅读 Bezier 页面.
向量插值
向量类型(Vector2 和 Vector3)也可以插值,向量自带了相关的便捷函数 Vector2.lerp() 和 Vector3.lerp()。
对于三次插值,还有 Vector2.cubic_interpolate() 和 Vector3.cubic_interpolate() ,它们执行 Bezier 式插值。
下面是从 A 点插值到 B 点的示例伪代码:
var t = 0.0
func _physics_process(delta):
t += delta * 0.4
$Sprite2D.position = $A.position.lerp($B.position, t)
private float _t = 0.0f;
public override void _PhysicsProcess(double delta)
{
_t += (float)delta * 0.4f;
Marker2D a = GetNode<Marker2D>("A");
Marker2D b = GetNode<Marker2D>("B");
Sprite2D sprite = GetNode<Sprite2D>("Sprite2D");
sprite.Position = a.Position.Lerp(b.Position, _t);
}
它将产生以下运动:
变换插值
也可以对整个变换进行插值(确保它们具有均一缩放,或者至少有相同的非均一缩放)。为此,可以使用函数 Transform3D.interpolate_with()。
下面是将猴子从位置1转换为位置2的例子:
使用以下伪代码:
var t = 0.0
func _physics_process(delta):
t += delta
$Monkey.transform = $Position1.transform.interpolate_with($Position2.transform, t)
private float _t = 0.0f;
public override void _PhysicsProcess(double delta)
{
_t += (float)delta;
Marker3D p1 = GetNode<Marker3D>("Position1");
Marker3D p2 = GetNode<Marker3D>("Position2");
CSGMesh3D monkey = GetNode<CSGMesh3D>("Monkey");
monkey.Transform = p1.Transform.InterpolateWith(p2.Transform, _t);
}
又会产生下面的动作:
平滑运动
插值可用于平滑运动, 旋转等. 下面是使用平滑运动跟随鼠标的圆圈的例子:
const FOLLOW_SPEED = 4.0
func _physics_process(delta):
var mouse_pos = get_local_mouse_position()
$Sprite2D.position = $Sprite2D.position.lerp(mouse_pos, delta * FOLLOW_SPEED)
private const float FollowSpeed = 4.0f;
public override void _PhysicsProcess(double delta)
{
Vector2 mousePos = GetLocalMousePosition();
Sprite2D sprite = GetNode<Sprite2D>("Sprite2D");
sprite.Position = sprite.Position.Lerp(mousePos, (float)delta * FollowSpeed);
}
如下:
This is useful for smoothing camera movement, allies following you (ensuring they stay within a certain range), and many other common game patterns.