매트릭스는 좌표 공간을 넘나드는 마법이다
영화 매트릭스에서 사람들은 숫자를 통해 한 세계에서 다른 세계로 넘어간다. 전화기를 들면 몸이 코드로 분해되고, 눈을 뜨면 완전히 다른 공간에 서 있다. 나는 이 영화의 제목이 우연이 아니라고 생각한다.
매트릭스(matrix)는 한국어로 행렬이다. 그리고 행렬이 실제로 하는 일이 정확히 그것이다. 한 좌표계의 점을 다른 좌표계의 점으로 옮기는 것. 한 세계에서 다른 세계로 이동시키는 것.
화면의 점 하나는 세계를 몇 번 건너온 것인가
게임 화면에 캐릭터의 손가락 끝 픽셀 하나가 찍혀 있다고 해보자. 그 점은 처음부터 거기 있던 게 아니다. 모델링 툴 안에서 캐릭터 자신을 기준으로 한 좌표에서 출발한다. 그다음 게임 월드 안 어딘가로 배치되고, 카메라가 보는 기준으로 다시 옮겨지고, 원근이 적용된 공간으로 또 한 번 옮겨진 뒤에야 화면 좌표가 된다.
이 과정이 전부 행렬 곱이다. 점 하나가 화면에 도달하기까지 최소 서너 번의 세계 전환이 일어난다. 렌더링 파이프라인에서 버텍스 셰이더가 하는 일도 결국 이 좌표계 변환이다. 정점 하나를 받아서 다른 좌표계의 정점으로 내보내는 것, 그 이상도 이하도 아니다.
학부 컴퓨터 그래픽스 수업에서 이 구조를 처음 이해했을 때의 감각을 나는 아직 기억한다. 그전까지 행렬은 시험지 위에서 숫자를 격자에 넣고 규칙대로 곱하던 계산 도구였다. 그게 화면에 무언가를 보이게 만드는 장치였다는 걸 알았을 때, 수학이 갑자기 눈에 보이는 것이 됐다.
좌표계는 하나가 아니라는 감각부터
여기서 먼저 잡아야 할 감각이 있다. 좌표계는 절대적인 게 아니라는 것.
얌얌코딩 채널의 게임 수학 Part1 재생목록에서는 데카르트 좌표계를 설명하며 이 점을 짚는다. 사람이 두 명 있으면 각자 자기 기준의 원점을 갖고, 원점이 다르면 그건 서로 다른 좌표계라는 설명이다. 같은 물체를 두 사람이 서로 다른 숫자로 부르게 되는 셈이다.
이게 바로 변환이 필요한 이유다. 서로 다른 원점을 쓰는 두 세계가 대화하려면 통역이 필요하고, 그 통역기가 행렬이다.
같은 영상에서는 좌표계가 엔진마다 다르다는 점도 설명한다. 왼손 좌표계는 Z축이 화면 안쪽으로 갈수록 커지고, 오른손 좌표계는 반대로 바깥쪽으로 올 때 커진다. 유니티는 왼손 좌표계를 쓰고, 엔진마다 선택이 다르다. 텍스처의 UV 좌표도 마찬가지여서, OpenGL 계열은 좌측 하단이 원점이다.
이 차이를 모르고 다른 엔진의 코드를 옮겨 붙이면 모델이 뒤집히거나 텍스처가 상하로 반전된다. 이런 종류의 버그를 만났을 때 셰이더 코드를 먼저 뒤지는 사람을 나는 여러 번 봤다. 하지만 원인은 대개 코드가 아니라 좌표계 약속의 차이다.
| 구분 | 왼손 좌표계 | 오른손 좌표계 |
|---|---|---|
| Z축 방향 | 화면 안쪽으로 갈수록 증가 | 바깥쪽(관찰자 쪽)으로 증가 |
| 대표 사용처 | 유니티 | 엔진에 따라 다름 |
| 변환 방법 | Z에 음수를 곱함 | 동일 |
행렬은 계산이 아니라 문장이다
행렬을 계산으로만 보면 지루하다. 4x4 격자 열여섯 개 숫자를 규칙대로 더하고 곱하는 일은 사람이 할 일이 아니다. 실제로 그 계산은 코드로 한 줄 써두면 컴퓨터가 대신한다.
앞의 영상에서 인상 깊었던 대목이 이 부분이다. 게임 수학은 문제풀이 수학과 다르다는 설명이다. 중고등학교 수학은 계산 방식을 익혀 점수를 얻는 것이 목적이었지만, 게임 개발의 수학은 개념을 이해하고 그것을 어떤 상황에 응용할지가 핵심이라는 것. 계산은 코드로 수식만 잘 짜두면 컴퓨터가 해준다는 말도 덧붙인다.
나도 이 관점에 동의한다. 다만 한 가지는 조금 다르게 본다. 계산을 컴퓨터에 맡긴다는 말이 곱셈 순서까지 몰라도 된다는 뜻은 아니다. 행렬 곱은 교환법칙이 성립하지 않는다. 회전 후 이동과 이동 후 회전은 완전히 다른 결과를 낸다. 이걸 손으로 한 번도 안 따져본 사람은 캐릭터가 제자리에서 돌지 않고 원을 그리며 도는 현상 앞에서 오래 헤맨다.
그래서 나는 이렇게 정리한다. 숫자 열여섯 개를 손으로 곱하는 연습은 필요 없다. 하지만 각 행렬이 “무엇을 무엇으로 바꾸는 문장"인지는 반드시 읽을 줄 알아야 한다.
음수의 발견이 쉽지 않았던 이유
같은 영상에서 좌표계의 역사를 설명하는 대목이 있다. 고대의 수학에는 좌표 개념이 없었고, 처음에는 양을 세기 위해 그림을 그렸다는 이야기다. 그림 그리는 비용이 크니 숫자라는 언어가 생겼고, 양을 팔기로 약속한 상황을 표현하려다 음수 개념이 나왔다는 흐름이다.
여기서 영상은 중요한 지적을 한다. 현실에는 음수를 표현할 수 있는 물체가 존재하지 않는다는 것. 양 다섯 마리는 눈에 보이지만 마이너스 양 세 마리는 눈에 보이지 않는다. 눈에 없는 것을 개념으로 만든 일이라 쉬운 발견이 아니었다는 이야기다.
이 대목이 나에게는 행렬을 이해하는 열쇠처럼 느껴졌다. 음수가 그랬듯, 행렬도 눈에 보이지 않는 것을 다루는 도구다. 좌표 변환은 만질 수 있는 물체가 아니다. “이 세계의 좌표를 저 세계의 좌표로 읽는 규칙"이라는 관계일 뿐이다. 그래서 처음 배울 때 손에 안 잡히는 게 자연스럽다. 1차원 수직선으로 좌우만 표현하던 사람이 x축과 y축을 얹어 평면을 표현하게 된 도약과, 좌표를 좌표로 옮기는 규칙 자체를 다루게 된 도약은 성격이 같다.
게임에서 쓰는 수학은 생각보다 좁다
행렬을 공부하겠다고 선형대수학 교재를 펴는 사람을 자주 본다. 나는 이 방법이 대부분 실패한다고 생각한다.
영상에서도 같은 지적이 나온다. 선형대수학 책에는 게임과 관련된 설명이 거의 없고, 결국 익숙한 문제풀이 방식으로 되돌아가게 된다는 것이다. 그래서 공식이 나열된 책보다 이야기와 서술이 있는 책을 봐야 이해가 빠르고 응용이 가능하며, 공식은 필요할 때마다 찾아보면 된다고 설명한다.
또 하나 영상에서 강조하는 부분은 게임에서 수학 지식이 제한적으로 쓰인다는 점이다. 오히려 과하게 깊이 알고 있는 내용이 이해를 방해할 수 있다고까지 말한다. 화면 하나에 좌표계 하나가 있다고 생각하면 편하다는 조언도 나온다.
내 경험도 이 말과 크게 어긋나지 않는다. 실무에서 쓰는 것은 결국 좁다.
- 벡터의 덧셈과 뺄셈 — 위치와 방향을 다루는 기본
- 내적 — 두 방향이 얼마나 같은 쪽을 보는지 판단
- 외적 — 수직인 방향, 즉 법선을 얻는 데 필요
- 이동·회전·크기 변환 행렬 — 물체를 세계에 배치
- 뷰 행렬과 투영 행렬 — 카메라가 보는 세계로의 전환
이 다섯 개를 “개념으로” 이해하면 상용 엔진에서 만나는 문제의 상당수가 설명된다. 반대로 이걸 건너뛰면 엔진이 제공하는 함수를 외워 쓰는 수준에 머문다.
좌표 변환이 안 잡힐 때 점검하는 순서
문제가 생겼을 때 나는 코드보다 좌표계를 먼저 의심한다. 아래 순서로 확인하면 원인이 빨리 좁혀진다.
- 이 값은 어느 좌표계 기준인가 (로컬인가 월드인가)
- 지금 곱하는 행렬은 어느 세계에서 어느 세계로 보내는 것인가
- 곱하는 순서가 의도한 순서가 맞는가 (회전 먼저인가 이동 먼저인가)
- 엔진의 좌표계가 왼손인가 오른손인가, 참고한 코드와 같은가
- 텍스처 UV의 원점이 좌측 상단인가 하단인가
- 부모 오브젝트가 있는가, 있다면 부모의 변환이 이미 적용되었는가
이 여섯 줄을 순서대로 물으면 대부분의 “왜 이상한 데 가 있지” 문제는 답이 나온다.
그래서 행렬을 왜 알아야 하는가
요즘 엔진은 좌표 변환을 거의 감춰준다. 트랜스폼 컴포넌트에 위치와 회전을 넣으면 알아서 된다. 그래서 몰라도 게임은 만들어진다.
하지만 문제가 생기는 순간 이야기가 달라진다. 셰이더를 직접 손대는 순간, 카메라가 이상하게 보이는 순간, 스키닝된 캐릭터의 무기가 손이 아닌 허공에 붙는 순간, 기준으로 삼을 것은 결국 좌표 변환에 대한 이해뿐이다. 게임 프로그래밍을 계속할 생각이라면 이 행렬과 좌표 변환만큼은 미루지 말고 제대로 봐야 한다고 나는 생각한다.
매트릭스에서 네오가 결국 코드 자체를 보게 되는 장면이 있다. 그 장면이 특별한 건 세계가 바뀌어서가 아니라, 세계를 굴리던 규칙이 드러나서다. 그래픽스 수업에서 내가 느낀 것도 그런 종류였다.
마치며
- 매트릭스는 행렬이고, 행렬은 한 좌표계를 다른 좌표계로 옮기는 장치다.
- 화면의 점 하나는 로컬에서 월드, 뷰, 투영을 거쳐 도착한 결과이며 그 전환은 전부 행렬 곱이다.
- 계산은 컴퓨터에 맡기되, 각 행렬이 어떤 세계에서 어떤 세계로 보내는지는 읽을 줄 알아야 한다.
- 행렬 곱은 순서가 바뀌면 결과가 바뀐다. 이 사실 하나가 수많은 버그의 원인이다.
- 좌표계는 절대적이지 않다. 엔진마다 손 방향과 UV 원점이 다르다는 전제를 항상 깔아두자.
자주 묻는 질문
Q. 게임 개발에 행렬이 정말 필수인가?
엔진만 쓰는 단계에서는 몰라도 진행된다. 다만 셰이더 작성, 카메라 제어, 본에 오브젝트를 붙이는 작업처럼 좌표계를 직접 다루는 순간부터는 피할 수 없다. 문제 해결 속도가 여기서 갈린다.
Q. 선형대수학 교재부터 봐야 할까?
나는 권하지 않는다. 참고한 영상에서도 선형대수학 책에는 게임 관련 설명이 거의 없고 문제풀이식 학습으로 돌아가기 쉽다고 지적한다. 이야기 형태로 서술된 게임 수학 자료를 먼저 보고, 공식은 필요할 때 찾아보는 편이 낫다.
Q. 왼손 좌표계와 오른손 좌표계는 어떻게 다른가?
Z축의 방향이 반대다. 왼손 좌표계는 화면 안쪽으로 갈수록 Z가 커지고, 오른손 좌표계는 관찰자 쪽으로 올 때 커진다. 유니티는 왼손 좌표계를 사용하며, 변환 자체는 음수를 곱하는 것으로 처리한다.
Q. x, y, z 말고 w는 왜 붙나?
동차 좌표라고 부르는 표현이다. 참고한 영상에서는 3D의 행렬 설명과 함께 다뤄야 할 주제라고 하며 우선은 이런 게 있다는 정도만 알고 넘어가라고 안내한다. 처음에는 x, y, z 세 축을 확실히 잡는 편이 낫다.
Q. 게임 수학은 어디까지 공부하면 충분한가?
벡터 연산, 내적, 외적, 이동·회전·크기 변환, 뷰와 투영 행렬 정도를 개념 수준에서 이해하면 실무의 상당 부분이 설명된다. 영상에서도 게임에서 쓰이는 수학 지식은 제한적이며 과하게 깊은 내용이 오히려 이해를 방해할 수 있다고 설명한다.
