Replicated

[Graphics] 좌표 변환 및 카메라 처리 본문

지식

[Graphics] 좌표 변환 및 카메라 처리

라구넹 2025. 5. 30. 15:00

Projection Matrix(투영 행렬)의 역할

3D 그래픽스와 컴퓨터 비전에서 3차원 공간의 좌표를 2차원 화면에 표시하기 위해 사용되는 행렬

 

주요 역할

1. 3D -> 2D 변환 (투영)

- 3차원 세계의 점을 2차원 화면 공간으로 변환

- 깊이(z값)는 보존되지만 위치는 2D 평면으로 투영됨

 

2. 시야(FOV), 종횡비(aspect ratio), 근/원거리 평면 설정

- ex. 멀리 있는 물체는 작게, 가까이 있는 물체는 크게 보이도록

 

3. 원근 투영(Perpective Projection), 직교 투영(Orthographic Projection)

 


 

Perspective Projection vs Perspective Projection

항목 Orthographic Projection (직교 투영) Perspective Projection (원근 투영)
원근감(거리감) 없음 (모든 물체 크기 동일) 있음 (멀면 작게, 가까우면 크게 보임)
투영선(ray) 평행 소실점으로 수렴 (눈 또는 카메라 중심)
소실점(vanishing point) 없음 존재함 (1점/2점/3점 투시)
주 용도 CAD, 설계도, UI, 전략게임 등 게임, 영화, 시뮬레이션 등 현실감 필요 시
수학적 복잡도 상대적으로 간단 더 복잡 (원근 변환, 깊이 보정 필요)
Z-depth 영향 없음 (z값과 화면 위치 무관) 있음 (깊이에 따라 스케일 변화)

 


 

View Matrix를 어떻게 구성?

카메라의 위치와 방향을 표현하여 월드 좌표계를 뷰 좌표계로 변환하는 행렬

-> 카메라를 움직이는 것처럼 보이게 장면 전체를 반대로 변환하는 역할

 

뷰 행렬의 구성 요소

1. Camera Position (eye): 카메라의 위치

2. Target (center): 카메라가 바라보는 대상 위치

3. Up Vector (up): 카메라의 위쪽 방향

 

LookAt 방식 예시

F = normalize(center - eye)      // Forward
R = normalize(cross(F, up))      // Right
U = cross(R, F)                  // Up (다시 정교화)

-------------------------------------------------------

|  R.x  R.y  R.z  -dot(R, eye) |
|  U.x  U.y  U.z  -dot(U, eye) |
| -F.x -F.y -F.z   dot(F, eye) |
|   0    0    0        1       |

 

버텍스의 좌표계 변환

모델 -> 월드 -> 뷰(카메라) -> 클립 -> NDC -> Screen Space

 

1. 모델 스페이스

- 모델 파일 안에 저장된 정점 위치, 모델 고유 좌표계

- 변환: Model Matrix -> 모델의 회전, 이동, 스케일하여 월드에 배치

 

2. 월드 스페이스

- 장면 전체에서의 위치 (모든 객체가 공존하는 좌표계)

- 변환: View Matrix -> 월드 공간을 카메라 기준 좌표계로 변환

 

3. 뷰 스페이스 (카메라 스페이스)

- 카메라가 (0, 0, 0)을 바라보는 좌표계, 모든 물체는 카메라를 기준으로 위치

- 변환: Projection Matrix -> 3D 공간을 2D 평면으로 투영

 

4. 클립 스페이스

- 최종 투영 결과, 여전히 4D 동차 좌표 (w값 존재)

- 이 단계에서 클리핑이 이루어짐 (near, far, view frustum 밖 제거)

- 변환: Perspective Divide -> (x, y, z) / w 를 통해 4D -> 3D 정규화

 

5. NDC (Normalized Device Coordinates)

- x, y, z가 [-1, 1] 범위로 정규화된 공간

- 이 좌표계에서만 Rasterization(화면 변환)가능

- 변환: Viewport Transformation -> NDC 좌표를 화면의 픽셀 위치로 변환

 

6. Screen Space

- 실제 픽셀 좌표계

 

v_screen = ViewportTransform(
              PerspectiveDivide(
                  ProjectionMatrix ×
                  ViewMatrix ×
                  ModelMatrix ×
                  v_local
              )
          )

전체 수식

 

* 동차 좌표계

흔히 아는 건 (x, y, z) -> 유클리드 좌표계

이건 행렬곱만으로 이동을 표현할 수 없음 (회전, 스케일은 가능)

-> 동차 좌표계 (homogeneous coordinates)

| 1  0  0  tx |
| 0  1  0  ty |
| 0  0  1  tz |
| 0  0  0  1  |   ×   (x, y, z, 1)^T

=> (x + tx, y + ty, z + tz, 1)

 

2D에선 (x, y, w)

3D에선 (x, y, z, w)

실제 좌표는 각각을 w로 나눈 값이 됨

 

장점

- 이동을 행렬곱으로 표현 가능

- 원근 투영을 자연스럽게 구현

 

구조

| R11  R12  R13  Tx |
| R21  R22  R23  Ty |
| R31  R32  R33  Tz |
|  0    0    0    1 |

* 한 물체의 Model Matrix (위치, 회전, 스케일). 이거 곱하면 결과는 4*1

Rij -> 회전과 스케일 정보가 들어가는 부분

Txyz -> 이동

마지막행: 동차 좌표 유지용 고정값

 

회전과 스케일은?

3x3 부분에 섞여 있음

분리 방법:

- 스케일: 열 벡터의 길이.. (ex. x축 스케일은 R11 ~ R31까지 제곱해서 더하고 루트)

- 회전: 스케일로 나눠주면 순수 회전 행렬임

 

회전

- 축을 다른 방향으로 바꾸는 것

스케일

- 축 방향의 벡터 길이를 늘리거나 줄이는 것

 

vertex_final = Translation × Rotation × Scale × vertex

스케일 적용하고 -> 회전하고 -> 마지막으로 이동함

 

| 2  0  0  0 |
| 0  1  0  0 |
| 0  0  3  0 |
| 0  0  0  1 |

Scale. x 두배 z 3배

 

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

* 그래픽스에서 회전은 보통 반시계가 양의 방향

시계 반대방향으로 90도 회전하는 행렬

원래의 점 (1, 0, 0, 1)에 곱하면 (0, 1, 0, 1)이 됨