Viewport 이론

Jaemyeong Lee·2025년 4월 2일

게임 서버1

목록 보기
211/220

🔍 Viewport란 무엇인가?

Viewport는 3D 그래픽에서 렌더링된 결과가 실제 화면에 표시되는 영역을 말한다.
쉽게 말해, 우리가 만든 3D 세계가 실제로 “어디에”, “어떻게” 보여질지를 결정하는 중요한 개념이다.
3D → 2D 변환의 마지막 단계가 바로 이 Viewport 변환이다.


📐 좌표 변환 흐름

3D 오브젝트가 화면에 그려지기까지의 변환 과정은 아래 순서로 이루어진다:

로컬(Local)
 → 월드(World)
   → 뷰(View / View Space)
     → 프로젝션(Projection / Clip Space)
       → 정규 디바이스 좌표(NDC)
         → Viewport 변환(Screen Space / 최종 2D 화면 좌표)

🧭 Viewport는 왜 필요한가?

우리가 3D 공간에서 마우스로 무언가를 클릭한다고 가정해보자.
마우스는 2D 좌표지만 실제로 선택하고자 하는 대상은 3D 물체다.
즉, 2D → 3D로 변환하는 과정(Unprojection) 이 반드시 필요하다.

이 과정에서 핵심 역할을 하는 게 바로 Viewport다.

예: 화면 중앙을 클릭했을 때,
카메라 위치에서 화면 중앙을 향해 레이저(ray) 를 쏘아
그 레이저가 맞은 오브젝트를 선택하는 방식.

이건 단순한 클릭뿐만 아니라 충돌 판정, AI 시야, 사거리 계산 등에도 응용된다.
다시 말해, Viewport는 2D 좌표를 3D 공간에서 유의미하게 쓰기 위한 게이트웨이 역할을 한다.


🧱 Viewport 클래스 설계

🔧 핵심 멤버

D3D11_VIEWPORT _vp;

DirectX가 제공하는 D3D11_VIEWPORT 구조체 하나만으로 필요한 정보를 모두 담을 수 있다.

🔄 주요 함수

  • Project: 3D 좌표 → 2D 스크린 좌표
  • Unproject: 2D 스크린 좌표 + 깊이 → 3D 좌표

🧮 좌표 변환 공식

📤 Project (3D → 2D)

Vec3 Viewport::Project(const Vec3& pos, const Matrix& W, const Matrix& V, const Matrix& P)
{
    Matrix wvp = W * V * P;
    Vec3 p = Vec3::Transform(pos, wvp);

    p.x = (p.x + 1.0f) * (_vp.Width / 2) + _vp.TopLeftX;
    p.y = (-p.y + 1.0f) * (_vp.Height / 2) + _vp.TopLeftY;
    p.z = p.z * (_vp.MaxDepth - _vp.MinDepth) + _vp.MinDepth;

    return p;
}

📥 Unproject (2D → 3D)

Vec3 Viewport::Unproject(const Vec3& pos, const Matrix& W, const Matrix& V, const Matrix& P)
{
    Vec3 p = pos;

    p.x = 2.f * (p.x - _vp.TopLeftX) / _vp.Width - 1.f;
    p.y = -2.f * (p.y - _vp.TopLeftY) / _vp.Height + 1.f;
    p.z = (p.z - _vp.MinDepth) / (_vp.MaxDepth - _vp.MinDepth);

    Matrix wvp = W * V * P;
    Matrix wvpInv = wvp.Invert();

    return Vec3::Transform(p, wvpInv);
}

🖼️ Graphics 클래스에 Viewport 적용

원래 Graphics 클래스에는 D3D11_VIEWPORT가 직접 들어있었지만,
우리는 이를 Viewport 클래스로 교체하고 별도로 관리하도록 했다.
이로써 Viewport의 폭/높이/위치/깊이값을 자유롭게 조작할 수 있게 된다.

Viewport 자체가 단순한 렌더링 옵션이 아니라,
입출력 좌표계의 핵심 매개체라는 점을 명확하게 알 수 있다.


🧪 테스트 – ViewportDemo

1. Viewport 조작

  • ImGui를 통해 Viewport의 크기, 위치를 실시간으로 조절
  • 조절 시 시야각의 변화도 확인 가능

2. 좌표 변환 테스트

  • 특정 3D 좌표를 Project하여 2D 좌표로 변환하고
  • 다시 Unproject로 3D로 역변환했을 때 원래의 3D 좌표로 정확히 복원됨을 확인

깊이값을 0에 가까이 두면 카메라 가까이
깊이값을 1에 두면 멀리 떨어진 곳이 된다


profile
李家네_공부방

0개의 댓글