보간법 (Interpolation)¶
보간법은 그래픽 프로그래밍에서 매우 기본적인 작업입니다. 그래픽 개발자로써의 시야를 넓히기 위해 이와 익숙해지는 것이 좋습니다.
기본적인 개념은 상태 A를 B로 전환하는 것입니다. 이 때, 값 t
는 그 둘 사이의 상태를 나타냅니다.
예를 들어 값 t
가 0이라면, 그에 해당하는 상태는 A입니다. 마찬가지로 값 t
가 1이라면 해당하는 상태는 B가 됩니다. 이 둘 사이의 모든 값들을 보간값 이라고 합니다.
두 실수(부동소수점)에 대해서, 단순한 보간식은 보통 다음과 같이 기술됩니다:
interpolation = A * (1 - t) + B * t
또한 종종 다음과 같이 간략화됩니다:
interpolation = A + (B - A) * t
한 값을 다른 값으로, 일정한 속도 로 전환하는 이러한 보간법을 선형적 (linear) 이라고 합니다. 즉, 선형 보간법 (Linear Interpolation) 이라고 하면 위의 단순한 식을 의미한다고 할 수 있습니다.
이 밖에도 여러 종류의 보간법이 있지만, 여기에선 설명하지 않겠습니다. 이 글을 읽은 뒤에 Bezier 를 읽어보는 것을 권장합니다.
벡터 보간¶
벡터 값 (Vector2 와 Vector3) 또한 보간될 수 있습니다. 이들은 보간을 수행하는 편리한 함수들을 갖추고 있는데, 각각 Vector2.linear_interpolate() 와 Vector3.linear_interpolate() 가 있습니다.
삼차 보간법의 경우엔, Vector2.cubic_interpolate() 스타일의 보간을 수행합니다.
다음은 점 A를 점 B로 이동하는 간단한 의사 코드입니다:
var t = 0.0
func _physics_process(delta):
t += delta * 0.4
$Sprite.position = $A.position.linear_interpolate($B.position, t)
private float _t = 0.0f;
public override void _PhysicsProcess(float delta)
{
_t += delta * 0.4f;
Position2D a = GetNode<Position2D>("A");
Position2D b = GetNode<Position2D>("B");
Sprite sprite = GetNode<Sprite>("Sprite");
sprite.Position = a.Position.LinearInterpolate(b.Position, _t);
}
위의 코드는 다음과 같은 모션을 보여줍니다:

변형 보간¶
변형 전체를 보간하는 것도 가능합니다 (이 경우 균일한 스케일, 또는 적어도 같은 비균일한 스케일을 가지고 있는지 확인하세요). 이 때는, Transform.interpolate_with() 함수를 사용할 수 있습니다.
아래는 원숭이 모델을 Position1에서 Position2로 변형하는 예입니다:

다음 의사 코드를 사용하면:
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(float delta)
{
_t += delta;
Position3D p1 = GetNode<Position3D>("Position1");
Position3D p2 = GetNode<Position3D>("Position2");
CSGMesh monkey = GetNode<CSGMesh>("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()
$Sprite.position = $Sprite.position.linear_interpolate(mouse_pos, delta * FOLLOW_SPEED)
private const float FollowSpeed = 4.0f;
public override void _PhysicsProcess(float delta)
{
Vector2 mousePos = GetLocalMousePosition();
Sprite sprite = GetNode<Sprite>("Sprite");
sprite.Position = sprite.Position.LinearInterpolate(mousePos, delta * FollowSpeed);
}
결과는 다음과 같습니다:

이것은 부드러운 카메라 움직임, 여러분을 일정 거리 내에서 따라다니는 동료, 그 밖의 수많은 일반적인 게임 패턴을 구현하는 데 도움이 됩니다.