핵심 정리
gl_Position = projection * view * model * vec4(position, 1.0);| 행렬 | 변환 |
|---|---|
| Model | object space -> world space |
| View | world space -> view space |
| Projection | view space -> clip space |
| MVP | object space -> clip space |
역할
Model 행렬은 모델의 로컬 좌표를 월드에 배치합니다. 위치, 회전, 크기가 여기에 들어갑니다. 같은 메시 데이터라도 model 행렬이 다르면 서로 다른 위치와 방향으로 그릴 수 있습니다.
View 행렬은 장면을 카메라 기준으로 바꿉니다. 실제로 카메라가 움직인다기보다, world space 전체를 카메라의 반대 방향으로 변환한다고 이해하면 됩니다.
Projection 행렬은 3D view space를 clip space로 보냅니다. perspective projection은 멀리 있는 것이 작아 보이게 만들고, orthographic projection은 거리에 따른 크기 변화를 없앱니다.
perspective divide
Projection 뒤에는 homogeneous coordinate의 w로 나누는 perspective divide가 일어납니다.
clip(x, y, z, w) -> ndc(x/w, y/w, z/w)이 과정 때문에 perspective projection에서 멀리 있는 물체가 작아집니다.
선택 기준
| 상황 | 볼 행렬 |
|---|---|
| 물체가 엉뚱한 위치에 있음 | model |
| 카메라 기준으로 뒤집힘 | view |
| 원근감이나 clipping이 이상함 | projection |
| 화면 밖으로 사라짐 | clip space, near/far |
| depth precision 문제 | projection near/far |
디버깅할 때는 한 번에 MVP 전체를 의심하지 말고, object -> world -> view -> clip을 단계별로 찍어보는 편이 안전합니다.
주의할 점
행렬 곱 순서는 표기 체계에 따라 다르게 보일 수 있습니다. GLSL 예시는 column vector 관례의 대표 형태입니다. 사용하는 API가 같은 순서를 기대하는지 확인해야 합니다.
또 near plane을 너무 작게 잡거나 far plane을 지나치게 크게 잡으면 depth precision이 나빠져 z-fighting이 잘 생깁니다.
참고 링크
1 sources