07. 투상 변환과 뷰 포트 변환

하이솝·2026년 5월 1일

컴퓨터그래픽스

목록 보기
7/9

2026.05.01

학습목표

  • 평행투상과 원근투상의 차이점을 이해한다.
  • 가시부피 설정방식을 이해한다.
  • glOrtho() 함수와 glPerspective() 함수 파라미터를 이해한다.
  • 전방 절단면은 되도록 시점에서 멀리 가져가는 이유를 이해한다.
  • 시점좌표, 절단좌표, 정규화 장치좌표, 화면좌표로의 변환과정을 이해한다.

01. 투상

투상(Projection) = 가시변환(Viewing Transformation)

  • 투상면(View Plane, Projection Plane)

  • 관찰자 위치(View Point, Eye Position)
    = 카메라 위치(Camera Position) = 투상중심(Center of Projection, COP)
    = 시점좌표계 원점(Origin of VCS)

  • 투상선(Projectors): 물체 곳곳을 향함

  • 시선(Line of Sight): WCS 원점 또는 초점을 향함

1-1 평행 투상(Parallel Projection)


원근법을 고려하지 않고 시점이 물체로부터 무한대의 거리에 있다고 간주

  • 투상선이 평행
  • 원래 물체의 평행선은 투상 후에도 평행
  • 시점과의 거리에 무관하게 같은 길이의 물체는 같은 길이로 투상

1-2 원근 투상(Perspective Projection)


시점이 물체로부터 유한한 거리에 있다고 간주

  • 투상선이 시점에서 출발하여 방사선 모양으로 펴져감
  • 카메라나 사람의 눈이 물체를 포착하는 방법

원근감
동일한 크기의 물체라도
시점으로부터 멀리 있는 것은 작게 보이고, 가까운 것은 크게 보임

소실점이 생겨남

원근변환(Perspective Transformation)

  • 직선→직선, 평면→평면
    직선은 그대로 직선을, 평면은 그대로 평면을 유지함

02. 지엘의 투상 변환

2-1 지엘의 평행 투상

투상: void glMatrixMode(GL_PROJECTION);
P' = MParallel · P

|1  0  0  0|
|0  1  0  0|
|0  0  0 -d|
|0  0  0  1|

역행렬이 존재하지 않음(특이변환)

해당 행렬은 암기해놓기

기본 평행투상

  • 모델 좌표, 전역 좌표, 시점 좌표 순서로 변환된 상태
  • P, P'은 시점 좌표계 기준의 좌표. 거리 d에 무관하게 동일
  • 특이변환(Singular Transformation): 역변환이 없는 변환
    • 점 P→P', Q→P'은 가능하지만, P'→P, P'→Q는 불가능함
    • 그러나 나중에 깊이 정보(P'→Q, P'→P 거리)를 활용하기 때문에,
      실제로 지엘은 이러한 변환을 가하지 않음
    • 개념적 설명임
    • 실제 지엘 내부에서는 투상결과 여전히 3차원 좌표가 유지됨
  • 눈이 원점에 있다고 가정하고 -z 방향으로 관찰하고 있다고 생각함
    모든 것은 을 기준으로 한 좌표

가시부피에 의한 평행투상

가시부피(View Volume): 장면의 범위를 지정할 필요성

void glOrtho(GLdouble left, righ, bottom, top, near, far)

  • 모두 카메라 기준 좌표계(눈)의 좌표
  • near, far은 [-near, -far]로 변환된다(-z축의 방향이기 때문)

정규화 가시부피

정규화 가시부피(CVV: Canonical View Volume)

  • 가로, 세로, 높이가 2인 정육면체로 투상
  • 정규화 변환(Normalization Transformation)
  • 변환 후 z축 방향이 반대가 됨
    계산의 편리를 위함

정규화 이유

  • 평행투상, 원근투상을 동일한 모습의 정규화 가시부피로 변형
    동일 파이프라인 사용

  • 정육면체를 기준으로 하면 연산이 간단함

  • 다양한 해상도의 화면 좌표계로 변환하기가 간단함

정규화 가시부피 변환

T변환(중점 이동) → S변환(크기변환) → R변환(z축 반대로 이동)

예제) 점(l,b,-n,1), (r,t,-f,1)의 변환 후 좌표를 구하시오.

이렇게 만들어진 좌표계를 절단 좌표계(Clip Coordinate System, CCS) 라고 함

2-2 지엘의 원근 투상


4행의 3열에 특정 숫자가 있다 = 원근 투상이다?

현재

|  x  |
|  y  |
| -z  |
| z/d |

에서 실제 3차원 공간의 x, y, z 좌표를 계산하기 위해서는
동차좌표의 마지막 요소(z/d)로 이전 요소로 나누는 작업이 필요함
이러한 작업을 원근분할(Perspective Division)이라고 함
평행투영은 원근분할이 필요 없고 원근투영만 필요함

정규화 가시 부피에 의한 투상

절단 사각뿔(frustum) = 절두체

  • 절두체 내부에 있는 물체만 관측 가능하고, 외부에 있는 물체는 관측 불가능함

원근 투상에서의 가시 부피 정규화


일반적 형태의 가시부피
void glFrustum(GLdouble left, right, bottom, top, near, far)

  • S, Sh 행렬은 x, y 값에 대해서 영향을 미치고,
    T 행렬은 z 값에 대해 영향을 미치고 있음
  1. (a) 형태의 모양을 좌우 대칭시켜서 (b) 모양으로 만듦
  2. (b) 형태의 모양을 늘려서 각도를 90º로 만듦
  3. (c) 형태의 좌표를 (d) 좌표로 표현함

  • 현재 정규화 과정에서 전방 절단면에 비해 후방 절단면 면적이 더 많이 줄어듦
    멀리 있는 것이 더 작게 보여야 하기 때문

  • T변환 후 마지막 요소는 -z가 되고, 원근 분할에
    x, y, z 값이 마지막 요소인 -z에 의해 나눠지는데,
    이로 인해 정규화 전의 중점과 후의 중점의 위치가 일치하지 않는다.
    반비례하기 때문

시점 좌표계에서 절단 좌표계로의 사상

  • 입력된 z값과 출력된 z값은 비례관계가 아닌, 곡선 형태의 관계가 성립

  • far 의 경우 기울기가 완만하기 때문이고
    near 의 경우 기울기가 급하기 때문에
    멀리 있는 물체는 깊이가 같다고 오판되기도 함

  • 따라서 near 값을 미는 방식으로 해결함

대칭적 원근투상

void gluPerspective(GLdouble fov, aspect, near, far);

  • 시야(Field of View, FOV): 상하 y축 방향의 시야각(0 ~ 180)
  • 종횡비(aspect, Aspect Ratio): x축 방향의 시야각(폭/높이)
    세로에 대한 가로의 비율 width/height
  • near, far: 눈으로부터의 거리
    단, z 값으로 나누어야 하므로 0보다 큰 값을 주어야 함

03. 지엘의 뷰 포트 변환

  • 코드 작성 순서는 아래에서 위 방향으로

  • ReShape 내에는 projection 변환만 사용하며,
    translate, scale 등의 변환은 display 내부에서 사용

  • 이전까지의 과정에서 정규화 가시부피 내에 모든 좌표를 표현

  • 이제부터는 실제 화면 (1024 등으로 표현되는)에
    어떻게 변환하여 출력할 것인가

정규화 장치좌표계(Normalized Device Coordinate System, NDCS)

  • 절단 이후 원근분할에 의해 물체 정점을 3차원 좌표로 변환한 것
    (x', y', z', 1) = (x/w, y/w, z/w, 1)

뷰포트 변환(Viewport Transformation)

  • 정규화 장치좌표계에서 화면 좌표계로 가는 작업
  • 화면 좌표계(Screen Coordinate System, SCS)
    뷰포트 좌표계(Viewport Coordinate System),
    윈도우 좌표계(Window Coordinate System)

3-1. 뷰포트 설정

void glViewport(GLint left, bottom, GLsizei width, height);

  • x, y 값만 변화됨

재 정규화

  • 정규화 가시부피에서의 z값의 범위인 [-1, +1] 사이를
    [0, 1] 사이로 사상

  • 정점 사이의 상대적인 깊이는 유지

  • 정규화 가시부피를 원점을 중심으로 해서
    z 방향으로 1/2 만큼 크기조절 변환을 가한 후,
    z 방향으로 1/2 만큼 평행 이동
    P' = T(0, 0, 0.5) * S(1, 1, 0.5) * P

변환 정리

1. 모델 변환 (Model Transformation)

  • 물체를 월드 공간에 배치
  • glTranslatef, glRotatef, glScalef

2. 시점 변환 (View Transformation)

  • 좌표 → 시점 좌표계
  • gluLookAt

3. 투상 변환 (Projection Transformation)

  • 시점 좌표 → 절단 좌표 (CVV)
  • 평행: glOrtho
  • 원근: gluPerspective, glFrustum

4. 원근분할 (Perspective Division)

  • 절단 좌표 → 정규화 장치 좌표 (NDC)
  • 동차좌표의 w로 나눔
  • OpenGL 내부에서 자동 처리

5. 뷰포트 변환 (Viewport Transformation)

  • NDC → 화면 좌표 (픽셀)
  • glViewport(x, y, width, height)
  • reshape 함수에서 설정

0개의 댓글