CGP 4-2 — 좌표 공간과 투영, GLSL
출처: SSU 컴퓨터 그래픽스 보조 슬라이드 — 3D 그래픽스를 위한 수학 (Part 2) 선행: CGP 4-1 — 3D 수학 기초 (벡터·행렬·변환), 07 — 3D 기하변환·뷰잉
본 강의의 7주차 슬라이드(SSU_CG_07)가 행렬 유도에 초점을 맞췄다면, 이 보조 슬라이드는 OpenGL/WebGL 의 실제 구현 관점에서 좌표 공간을 다시 정리합니다. 셰이더에 한 줄짜리 gl_Position = P * V * M * pos 로 압축되는 그 파이프라인을 단계별로 풀어 봅니다.
1. 좌표 공간 (Coordinate Spaces) — 6단계 ⭐️
출처: 슬라이드 1~11
3D 그래픽스에서 한 정점이 화면 픽셀이 되기까지 거치는 좌표 공간 6개. 각 단계 사이의 변환 행렬 이 핵심입니다.
The Grand Pipeline — Model → Screen
6주차Model Space
오브젝트 자체의 로컬 좌표계 (원점 기준).
World Space
Model Matrix M 을 곱해 전역 공간에 배치.
View Space
View Matrix V 로 카메라 기준으로 재정렬.
NDC Space
Projection 적용 + 원근 분할 → [-1, 1] 정규화.
Screen Space
최종 픽셀 좌표로 변환하여 화면에 출력.
| # | 공간 (Space) | 별칭 | 원점 / 의미 | 진입 변환 |
|---|---|---|---|---|
| 1 | 모델 공간 | Local Space, Object Space | 오브젝트 자체의 중심 | — (모델링 결과) |
| 2 | 월드 공간 | World Space | 장면 전체의 원점 | 모델 행렬 |
| 3 | 뷰 공간 | View / Eye / Camera Space | 카메라 위치 = 원점, 카메라가 -z 축을 바라봄 | 뷰 행렬 |
| 4 | 클립 공간 | Clip Space | 가시 영역 판별을 위한 동차 좌표 (w 포함) | 투영 행렬 |
| 5 | NDC | Normalized Device Coordinates | 모든 축이 인 정규화 큐브 | 원근 분할 () |
| 6 | 스크린 공간 | Screen / Window Space | 픽셀 단위 좌표 (좌상단 또는 좌하단 원점) | 뷰포트 변환 |
1.1 정리 흐름
Position (Local)
→ ×M → World
→ ×V → View
→ ×P → Clip ← 셰이더가 출력하는 gl_Position
→ ÷w → NDC ← GPU 가 자동 수행 (Perspective Divide)
→ 뷰포트 → Screen ← GPU 가 자동 수행셰이더가 책임지는 구간은 Local → Clip 까지. 이후의 원근 분할과 뷰포트 매핑은 GPU 고정 단계.
2. 뷰 행렬 (View Matrix) — LookAt 방식 ⭐️
출처: 슬라이드 12~13
월드 공간을 카메라 기준으로 재정렬하는 행렬. 본질은 "카메라를 원점으로 + 카메라의 보는 방향을 -z 축으로" 정렬하는 합성 변환.
2.1 LookAt 의 세 파라미터
| 파라미터 | 의미 |
|---|---|
| Eye | 카메라의 위치 (월드 좌표) |
| At | 카메라가 바라보는 목표점 |
| Up | 카메라의 위쪽 방향 (대개 ) |
2.2 행렬 구성
뷰 행렬은 두 행렬의 합성:
- 이동: 카메라(Eye)를 월드 원점으로 가져오기 →
- 회전: 카메라의 UVN 축을 월드 XYZ 축에 정렬 →
UVN 기저 의 구체적 유도는 07 — 3D 변환·뷰잉 5절을 참고. 여기서는 결과만 사용.
2.3 회전 행렬 의 직교성
UVN 은 정규직교 기저 이므로 회전 행렬 의 역행렬은 전치 만으로 구할 수 있습니다 (). 이 성질이 GLSL 의 inverse() 호출을 피하게 해 주는 표준 최적화.
3. 투영 행렬 (Projection Matrix) ⭐️
출처: 슬라이드 14~17
3.1 원근 투영 (Perspective Projection)
거리에 따라 객체가 작아지는 사람 눈에 가까운 투영. WebGL/OpenGL 의 perspective(fovy, aspect, near, far) 한 줄로 생성됩니다.
| 파라미터 | 의미 |
|---|---|
| fovy | 세로 시야각 (Field of View, Y축 기준 — 라디안 또는 도) |
| aspect | 화면 종횡비 = width / height |
| near | 가까운 클리핑 평면까지의 거리 |
| far | 먼 클리핑 평면까지의 거리 |
뷰 볼륨 모양은 프러스텀(잘린 사각뿔).
Camera Viewing & Projection
6주차3.2 평행 투영 (Orthographic Projection)
거리와 무관하게 객체 크기가 유지되는 투영. CAD/설계 도면용. 파라미터:
| 파라미터 | 의미 |
|---|---|
| left, right | 좌/우 평면의 x좌표 |
| bottom, top | 하/상 평면의 y좌표 |
| near, far | 가까운/먼 평면까지의 거리 |
뷰 볼륨 모양은 직육면체(Box).
3.3 두 투영 비교
| 원근 투영 | 평행 투영 | |
|---|---|---|
| 뷰 볼륨 | 프러스텀 | 직육면체 |
| 거리 효과 | 멀수록 작아짐 | 크기 유지 |
| 활용 | 게임·VR·시네마틱 | CAD·설계도·UI 오버레이 |
w 성분 | 가 들어가 원근 분할 발생 | 유지 (분할 없음) |
원근 투영 행렬의 마지막 행이
[0, 0, -1, 0]인 핵심 이유: 곱셈 결과의w에-z가 들어가 원근 분할(Perspective Divide) 의 분모를 자동으로 준비함. 이 한 칸이 "멀면 작다"의 수학적 본체.
4. OpenGL · GLSL 에서의 변환
출처: 슬라이드 18~21
4.1 Vertex Shader 의 역할
정점 데이터를 입력받아 클립 공간 좌표(gl_Position) 를 출력하는 것이 vertex shader 의 1차 책임. 색상·노멀 등 추가 출력은 별도 varying 으로 전달.
4.2 표준 변환 한 줄
#version 300 es
uniform mat4 uProjection; // P
uniform mat4 uView; // V
uniform mat4 uModel; // M
in vec3 aPosition; // local space
void main() {
gl_Position = uProjection * uView * uModel * vec4(aPosition, 1.0);
}행렬 곱이 오른쪽에서 왼쪽 으로 적용됨을 기억:
position(local)
→ uModel → world
→ uView → view
→ uProjection → clip ← gl_Position4.3 GLSL 내장 변수
| 변수 | 종류 | 의미 |
|---|---|---|
gl_Position | out (vertex) | 클립 공간 좌표. 셰이더가 반드시 써 줘야 함 |
gl_VertexID | in (vertex) | 현재 처리 중인 정점의 인덱스 |
gl_FragCoord | in (fragment) | 현재 픽셀의 윈도우 좌표 (x, y, z, 1/w) |
gl_PointSize | out (vertex) | 점(point) 프리미티브를 그릴 때 픽셀 크기 |
4.4 MVP 합성 — CPU에서 미리
수백만 정점이 같은 변환을 거치므로, P * V * M 을 CPU 에서 한 번만 곱해 uMVP 로 넘기는 것이 표준 최적화입니다.
uniform mat4 uMVP;
void main() {
gl_Position = uMVP * vec4(aPosition, 1.0);
}