OpenGL

OpenGL 공부하기 #4 - 행렬과 변환

NAEU 2025. 7. 14. 23:13

1. glm 라이브러리 기본

GLM (OpenGL Mathematics)은 GLSL과 유사한 문법을 사용하는 수학 라이브러리

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

 

2. Transformations의 종류

Translation (이동)

glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(x, y, z));
  • 객체를 x, y, z 방향으로 이동시킴
  • 보통 model 행렬에서 사용

Scaling (크기 조절)

model = glm::scale(model, glm::vec3(sx, sy, sz));
  • 비율로 객체를 확대/축소
  • 균일 스케일: glm::vec3(s, s, s)

Rotation (회전)

model = glm::rotate(model, glm::radians(angle), glm::vec3(ax, ay, az));
  • angle: 회전 각도 (라디안 단위)
  • vec3: 회전축

예) Z축 회전:

glm::rotate(model, glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f));

 

3. Model Matrix (모델 행렬)

Local Space → World Space

  • 로컬 좌표를 월드 좌표로 변환
  • 객체 개별 위치, 회전, 스케일 등을 반영
  • 순서: 크기 회전  위치
glm::mat4 model = glm::mat4(1.0f); 
model = glm::scale(model, glm::vec3(scale, scale, scale));
model = glm::rotate(model, glm::radians(angle), glm::vec3(0, 0, 1)); 
model = glm::translate(model, glm::vec3(x, y, z));

 

쉐이더에 전달하는 방법:

glm::mat4 mvp = projection * view * model;
glUniformMatrix4fv(mvpLocation, 1, GL_FALSE, glm::value_ptr(mvp));

4. View Matrix (뷰 행렬)

World Space → View (Camera) Space

  • 카메라 위치/시점 기준으로 좌표를 변환
  • glm::lookAt() 함수를 자주 사용
glm::mat4 view = glm::lookAt( 
	glm::vec3(0.0f, 0.0f, 3.0f), // Camera position 
	glm::vec3(0.0f, 0.0f, 0.0f), // Target 
	glm::vec3(0.0f, 1.0f, 0.0f) // Up 
);

5. Projection Matrix (투영 행렬)

View Space → Clip Space

  • 원근 투영: 원근감 있는 장면 표현
glm::mat4 projection = glm::perspective(glm::radians(45.0f), aspect, 0.1f, 100.0f);
  • 직교 투영: 일정한 비율 유지
glm::mat4 projection = glm::ortho(left, right, bottom, top, near, far);

 

6. Clip Space (클립 공간)

-w ~ +w 사이로 정점 위치가 재조정됨.

  • MVP = projection * view * model 을 적용한 후의 결과는 Clip Space에 있음.
  • GPU는 이 공간에서 Clipping (잘라냄) 을 수행함. 즉, 화면 밖의 좌표를 제거함.
  • 이 시점에서는 정점 좌표는 vec4(x, y, z, w) 형태임.
gl_Position = projection * view * model * vec4(vertexPos, 1.0);

 

7. NDC (Normalized Device Coordinates)

Clip Space → NDC (나눗셈 처리)

  • GPU가 자동으로 gl_Position.xyz / gl_Position.w 를 해줌
  • 결과는 각 축의 값이 -1.0 ~ 1.0 사이로 정규화됨
    (X: 왼쪽 -1, 오른쪽 1 / Y: 아래 -1, 위 1 / Z: near -1, far 1 or 0~1)

8. Viewport Transform → Screen Space

NDC → Screen Space

  • glViewport(x, y, width, height) 설정값 기준으로 변환
  • -1 ~ 1 범위의 NDC가 → 실제 화면 픽셀 좌표로 매핑됨
 
glViewport(0, 0, screenWidth, screenHeight);
  • NDC (0, 0) → 화면의 정중앙
  • NDC (1, 1) → 화면 오른쪽 위 모서리
  • NDC (-1, -1) → 화면 왼쪽 아래 모서리

전체 수식 정리

glm::mat4 mvp = projection * view * model; 
gl_Position = mvp * vec4(vertex, 1.0f);

 

파이프라인 흐름:

[Local Space] → model → [World Space] → view → [View (Camera) Space] → projection → [Clip Space] → perspective divide → [NDC] → viewport transform → [Screen Space]