Make Unreal REAL.
article thumbnail
이득우의 게임 수학

 

이제 절두체를 구성하는 6개의 평면에 대한 방정식을 구해 카메라 시야 영역에서 벗어난 게임 오브젝트들을 솎아내는 기능인 절두체 컬링을 구현해본다.

 

근평면과 원평면을 제외한 4개의 측면 평면은 원점을 포함하기 때문에 원점으로부터의 거리를 의미하는 d의 값은 0이 된다.

  • 따라서, 크기가 1인 법선 벡터만 구하면 4개의 측면 평면에 대한 방정식을 얻을 수 있다.

 

 

우선 절두체 상단 평면에 대해 생각해보자.

 

측면에서 보았을 때 오른쪽은 뷰 공간의 -z축에 대응되고, 위쪽은 y축에 대응된다.

 

오른쪽을 향하는 벡터 (0, 0, -1)을 반시계 방향으로 θ/2만큼 회전하고 90°만큼 더 회전하면 상단 평면의 법선 벡터를 구할 수 있다.

 

 

(0, 0, -1)을 반시계 방향으로 θ/2만큼 회전한 벡터는 다음과 같다.

 

 

이 벡터를 반시계 방향으로 90°만큼 더 회전하면 상단 평면의 법선 벡터를 구할 수 있다.

 

 

상단 평면을 원점을 포함하므로 거리 d는 0이 되고, 평면의 방정식은 다음과 같다.

 

절두체 상단 평면의 방정식

 

같은 방식으로 나머지 세 평면의 방정식도 구하면 다음과 같다.

 

절두체 하단 평면의 방정식
절두체 좌측 평면의 방정식
절두체 우측 평면의 방정식

 

이제 근평면과 원평면의 방정식을 구해본다.

 

근평면은 원점을 바라보고 있으며 원점으로부터의 거리가 n이므로 방정식의 d 값은 n이 된다.

 

근평면의 법선 벡터는 (0, 0, 1)이므로, 근평면의 방정식은 다음과 같다.

 

절두체 근평면의 방정식

 

원평면은 원점의 반대 방향을 바라보고 있으며 원점으로부터의 거리가 f이므로 방정식의 d 값은 f가 된다.

 

원평면의 법선 벡터는 (0, 0, -1)이므로, 원평면의 방정식은 다음과 같다.

 

절두체 원평면의 방정식

 

평면의 방정식을 다룰 때 주의할 점은, 방향 정보가 포함되어 있기 때문에 함부로 수식을 옮기면 안 된다는 것이다.

  • 아래 방정식은 평면의 위치는 동일하지만, 방향이 반대인 평면이 된다.

 

 

책의 예제인 CK소프트렌더러에서는 법선 벡터와 d 값을 저장하는 평면 6개를 통해 절두체를 정의했다.

 

// 책의 예제인 CK소프트렌더러에 정의된 절두체
struct Frustum
{
...

    // Y+, Y-, X+, X-, Z+, Z- 순으로 저장
    array<Plane, 6> Planes;

...
};
// 책의 예제인 CK소프트렌더러에서 판별 상태를 저장하는 열거형
enum class BoundCheckResult : UINT32
{
    Outside = 0,
    Intersect,
    Inside
};

 

책의 예제인 CK소프트렌더러에서 임의의 점 P가 절두체 내부 혹은 외부에 있는지 판정하는 부분이다.

 

// 책의 예제인 CK소프트렌더러에서 임의의 점에 대한 평면 내외부 판정 로직
FORCEINLINE constexpr bool Plane::IsOutside(const Vector3& InPoint) const
{
    return Distance(InPoint) > 0.f;
}

// 임의의 점에 대한 절두체 내외부 판정 로직
FORCEINLINE constexpr BoundCheckResult Frustum::CheckBound(const Vector3& InPoint) const
{
    for (const Plane& p : Planes)
    {
        if (p.IsOutside(InPoint))
        {
            return BoundCheckResult::Outside;
        }
        else if (Math::EqualsInTolerance(p.Distance(InPoint), 0.f))
        {
            return BoundCheckResult::Intersect;
        }
    }
    return BoundCheckResult::Inside;
}

 

평면의 방정식을 이용해 절두체 컬링을 적용했다.

 

하지만 아직 종횡비를 고려하지 않아 양옆에 빈 공간이 생겼다.

 

또, 오브젝트의 위치를 이용해 절두체 내외부 판정을 진행하기 때문에 가장자리에서 오브젝트가 갑자기 사라지거나 불쑥 생겨나는 현상이 있다.

  • 이것은 바운딩 볼륨을 통해 해결할 수 있다.

 

profile

Make Unreal REAL.

@diesuki4

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그