행렬
행렬을 이용하면 체계적으로 공간을 빠르게 변환시킬 수 있습니다.
‘이득우의 게임 수학’을 읽고 내 나름대로의 이해를 토대로 정리한 글이다. 틀린 부분이 있을 수도 있다.
벡터와 벡터의 덧셈, 스칼라와 벡터의 곱셈, 삼각 함수를 이용하여 물체의 이동과 회전에 대해서 공부했다.
지금까지는 물체의 이동, 크기 조절, 회전을 한 번에 처리할 수 없었다.
실시간으로 반응하는 게임을 만들기 위해서는 사소한 연산들도 한 번에 처리하는 것이 중요하다.
연산량이 줄어야만 속도가 빨라지기 때문이다. 연산량을 줄이기 위해서 사용할 수 있는 것이 행렬이다.
선형성
행렬을 이해하기 위해서는 선형성에 대한 이해가 필요하다.
스칼라와 벡터의 곱셈의 결과는 원점을 지나는 직선 상에 위치하는 벡터다.
이렇게 직선의 형태를 띠는 것을 선형성을 가진다고 한다.
직관적으로 직선의 형태를 띠는 것이 선형성이라고 하지만 이를 수학적으로 구분할 수 있는 방법이 필요하다.
이때 우리는 가법성과 1차 동차성을 만족하면 선형성을 보인다고 한다.
가법성: $f(x_1 + x_2) = f(x_1) + f(x_2)$
1차 동차성: $f(kx) = k \cdot f(x)$
직선의 형태를 가진 그래프라면 반드시 선형성을 가지는 것일까?
예를 들어 $y = ax + b$의 함수를 생각해보자.
먼저 가법성을 만족하는지 살펴보자.
$a(x_1 + x_2) + b = ax_1 + ax_2 + b$
$ax_1 + b + ax_2 + b = ax_1 + ax_2 + 2b$
$\therefore f(x_1 + f_2) \neq f(x_1) + f(x_2)$
그 다음으로 1차 동차성을 만족하는지 살펴보자.
$k(ax + b) = kax + kb$
$a(kx) + b = kax + b$
$\therefore f(kx) \neq kf(x)$
직선의 형태를 가짐이 반드시 선형성을 가짐을 의미하는 것이 아니다.
선형성은 직선의 성질만을 의미하는 것이 아닌, 두 집합의 순수한 비로 구성된 1차적 대응 관계를 의미한다.
선형 변환
$\mathbb{R}$ 집합에서 선형성이 가지는 의미와 선형 함수에 대해서 살펴봤다.
이제는 이를 확장하여 두 집합의 순서쌍을 가지는 벡터 공간에서의 선형성과 선형 함수에 대해서 알아보자.
벡터의 $x$축 요소와 $y$축 요소가 독립적으로 계산된다는 것을 알고 있다.
또, 선형성은 두 집합의 순수한 비로 구성된 1차적 대응 관계라는 것을 알고 있다.
따라서 벡터 공간에서의 선형 함수는 다음과 같이 구성됨을 알 수 있다.
$f(\vec{v}) = f(x, \;y) = (ax + by, \;cx + dy)$
그렇다면 위의 함수가 선형성을 만족하는지 살펴보자.
먼저 가법성을 만족하는지 살펴보자.
$f(\vec{v_1} + \vec{v_2}) = f(x_1 + x_2, y_1 + y_2)$
$\qquad \qquad \;\;\, = (a(x_1 + x_2) + b(y_1 + y_2),\; c(x_1 + x_2) + d(y_1 + y_2))$$f(\vec{v_1}) + f(\vec{v_2}) = (ax_1 + by_1, \;cx_1 + dy_1) + (ax_2 + by_2,\; cx_2 + dy_2)$
$\qquad \qquad \qquad = (a(x_1 + x_2) + b(y_1 + y_2),\; c(x_1 + x_2) + d(y_1 + y_2))$$\therefore f(\vec{v_1} + \vec{v_2}) = f(\vec{v_1}) + f(\vec{v_2})$
그리고 1차 동차성을 만족하는지 살펴보자.
$f(k\vec{v}) = (akx + bky,\; ckx + dky)$
$\qquad \;\;\, = (kax + kby,\; kcx + kdy)$$k \cdot f(\vec{v}) = k(ax + by,\; cx + dy)$
$\qquad \quad \;\, = (kax + kby,\; kcx + kdy)$$\therefore f(k\vec{v}) = k \cdot f(\vec{v})$
$f(\vec{v})$는 선형성과 1차 동차성을 만족하기 때문에 선형 함수다.
표준 기저 벡터의 선형 결합으로 생선된 벡터 공간을 선형성을 지닌다.
벡터 공간을 선형 함수로 변환시킨 새로운 벡터 공간도 기저벡터의 선형 결합으로 생성되므로 선형성을 지닌다.
이렇게 두 공간이 서로 동일한 구조를 지닐 때 두 공간의 대응 관계를 변환이라고 한다.
즉, 선형 함수와 선형 변환은 기능적으로는 완전히 동일하며 의미만 다르다고 생각하면 된다.
선형 변환은 게임 속에서 가상 세계를 구축하는 데 필요한 모든 변환의 기초가 된다.
따라서 선형 변환을 빠르게 계산할 수 있는 도구가 필요한데 그것이 행렬이다.
행렬
행렬은 수를 사각형의 형태로 행과 열을 맞춰 배열한 테이블이다.
$n \times m$ 행렬은 $n$개의 행과 $m$개의 열을 가진다.
예를 들어 $2 \times 3$ 행렬이 있다고 하면 다음과 같이 표기한다.
$\begin{bmatrix} a & b & c \newline d & e & f \end{bmatrix}$
행렬은 벡터를 나타내는 데 사용할 수 있다.
벡터를 표현하는 데 2가지 방법이 있으며 $A$를 열벡터, $B$를 행벡터라고 한다.
$A =\begin{bmatrix} x \newline y\end{bmatrix} \newline$
$B = \begin{bmatrix} x & y \end{bmatrix}$
행렬은 선형 변환을 나타내는 데 사용할 수 있다.
예를 들어 $f(\vec{v}) = (ax + by,\; cx + dy)$와 같은 2차원 선형 변환은 다음과 같이 표시한다.
$A = \begin{bmatrix} a & b \newline c & d \end{bmatrix}$
위와 같이 행의 수와 열의 수가 같은 행렬을 정방 행렬이라고 한다.
정방 행렬은 2개의 행벡터나 2개의 열벡터를 가진다고 할 수 있다.
행렬의 연산
행렬은 다양한 연산이 있지만 가상 세계를 구축하는 데 필요한 연산은 다음과 같다.
- 행렬과 행렬의 덧셈
- 행렬과 스칼라의 곱셈
- 행렬의 전치
- 행렬과 행렬의 곱셈
행렬과 행렬의 덧셈
행렬과 행렬의 덧셈은 행렬의 각 요소를 더하면 된다.
$A = \begin{bmatrix} 1 & 2 \newline 3 & 4 \end{bmatrix},\quad B = \begin{bmatrix} 2 & 4 \newline 6 & 8 \end{bmatrix} \newline \newline$
$A + B = \begin{bmatrix} 1 + 2 & 2 + 4 \newline 3 + 6 & 4 + 8 \end{bmatrix} = \begin{bmatrix} 3 & 6 \newline 9 & 12 \end{bmatrix}$
행렬과 스칼라의 곱셈
행렬과 스칼라의 곱셈은 행렬의 요소에 스칼라를 각각 곱해준 것과 같다.
$A = \begin{bmatrix} 1 & 2 \newline 3 & 4 \end{bmatrix},\quad K = 3$
$K \cdot A = 3 \cdot \begin{bmatrix} 1 & 2 \newline 3 & 4 \end{bmatrix} = \begin{bmatrix} 3 & 6 \newline 9 & 12 \end{bmatrix}$
행렬의 전치
행렬의 전치 연산을 통해서 얻는 행렬을 전치 행렬이라고 한다.
기존 행렬을 $A$라고 했을 때 전치 행렬은 $A^T$라고 표기한다.
행렬의 전치 연산은 행과 열을 바꾸는 연산이다.
$A = \begin{bmatrix} 1 & 2 \newline 3 & 4 \end{bmatrix}$
$A^T = \begin{bmatrix} 1 & 3 \newline 2 & 4\end{bmatrix}$
행렬과 행렬의 곱셈
행렬과 행렬의 곱셈은 앞의 행렬의 행벡터와 뒤의 행렬의 열벡터를 곱하는 연산이다.
행렬과 행렬의 곱셈은 항상 할 수 있는 것이 아니다.
앞의 행렬의 열의 개수와 뒤의 행렬의 행의 개수가 같은 경우에만 할 수 있다.
$A = \begin{bmatrix} 1 & 2 \newline 3 & 4 \end{bmatrix},\quad B = \begin{bmatrix} 2 & 4 \newline 6 & 8 \end{bmatrix} \newline \newline$
$A \times B = \begin{bmatrix} 1 & 2 \newline 3 & 4 \end{bmatrix} \cdot \begin{bmatrix} 2 & 4 \newline 6 & 8 \end{bmatrix} = \begin{bmatrix} 1\cdot2 + 2\cdot 6 & 1 \cdot 4 + 2 \cdot 8 \newline 3 \cdot 2 + 4 \cdot 6 & 3 \cdot 4 + 4 \cdot 8\end{bmatrix}$
$\qquad \;\;\;\,= \begin{bmatrix} 14 & 20 \newline 30 & 44\end{bmatrix} $
행렬의 곱셈과 관련하여 알아야 하는 성질들이 있다.
증명은 생략하도록 하겠다.
- $A \cdot B \neq B \cdot A$
- $A \cdot (B \cdot C) = (A \cdot B) \cdot C$
- $(A \cdot B)^T = B^T \cdot A^T$
행렬 곱의 결과는 $f(x, y) = (ax + by,\; cx + dy)$의 결과와 동일하다.
따라서 $2 \times 2$ 행렬 곱 연산은 2차원 선형 변환에 대응하는 함수와 같다.
이는 2차원 벡터에 선형 변환을 적용해 새로운 벡터를 생성하는 작업으로 해석할 수 있다.
정방행렬 곱셈의 해석
$2 \times 2$ 정방행렬이 2차원 선형 변환에 대응한다면 정방 행렬의 곱셈의 합성 함수와 동일한 개념이다.
벡터 $\vec{v}$와 $2\times 2$ 정방행렬인 $A$와 $B$를 다음 순서로 연산한다고 하자.
$B \cdot A \cdot \vec{v}$
선형 변환 $A$로 생성되는 공간을 $U$, 선형 변환 $B$로 생성되는 공간을 $W$라고 한다면 벡터 $\vec{v}$가 다음의 대응 관계를 가진다.
$\vec{v} \rightarrow \vec{u} \rightarrow \vec{w}$
정방행렬의 곱셈으로 이를 실제로 확인해보자.
$A = \begin{bmatrix} a & b \newline c & d \end{bmatrix}, \quad B = \begin{bmatrix} e & f \newline g & h \end{bmatrix}, \quad \vec{v} = \begin{bmatrix} x \newline y \end{bmatrix}$
$A \cdot \vec{v} = \vec{u} = \begin{bmatrix} a & b \newline c & d \end{bmatrix} \cdot \begin{bmatrix} x \newline y \end{bmatrix} = \begin{bmatrix} ax + by \newline cx + dy\end{bmatrix}$
$B \cdot \vec{u} = \vec{w} = \begin{bmatrix} e & f \newline g & h \end{bmatrix} \cdot \begin{bmatrix} ax + by \newline cx + dy\end{bmatrix} = \begin{bmatrix} e(ax + by) + f(cx + dy) \newline g(ax + by) + h(cx + dy)\end{bmatrix}$
그리고 결합 법칙이 만족하는지도 확인해보자.
$B \cdot A = \begin{bmatrix} e & f \newline g & h\end{bmatrix} \cdot \begin{bmatrix} a & b \newline c & d\end{bmatrix} = \begin{bmatrix}ae + cf & eb+fd \newline ag + ch & bg + dh\end{bmatrix}$
$ (B \cdot A) \cdot \vec{v} = \begin{bmatrix}ae + cf & eb+fd \newline ag + ch & bg + dh\end{bmatrix} \cdot \begin{bmatrix} x \newline y\end{bmatrix} = \begin{bmatrix}x(ae + cf) + y(eb + fd) \newline x(ag + ch) + y(bg + dh)\end{bmatrix}$
$\therefore B \cdot(A \cdot \vec{v}) = (B \cdot A) \cdot \vec{v}$
결합 법칙을 만족하는 행렬 곱은 그래픽 연산에서 유용하게 사용된다.
예를 들어 100개의 점으로 구성된 물체가 5번의 선형 변환을 거쳐야 한다고 하자.
$ E \cdot D \cdot C \cdot B \cdot A \cdot \vec{v_1}$
$\qquad \;\;\quad \cdots$
$ E \cdot D \cdot C \cdot B \cdot A \cdot \vec{v_{100}}$
연산 횟수를 생각해보면 점 100개를 5번 선형 변환해야 하기 때문에 500회의 연산 횟수를 가진다.
이때 결합 법칙이 성립하는 행렬 곱을 사용하면 $F = E \cdot D \cdot C \cdot B \cdot A$라고 만들 수 있다.
즉, $E \cdot D \cdot C \cdot B \cdot A$를 캐싱해두고 점 100개만 행렬 곱 연산을 하면 된다.
결과적으로는 $F$를 만드는 데 필요한 4번의 행렬 곱과, 점 100개를 선형 변환하는 1번의 행렬 곱만이 필요하다.
$4 + 1 \cdot 100 = 104$
행렬 곱을 이용하여 연산량을 500회에서 104회로 드라마틱하게 줄일 수 있다.
행렬의 설계
앞서 $2 \times 2$ 정방행렬이 2차원 선형 변환에 해당함을 확인했다.
이를 토대로 크기 변환 행렬, 회전 변환 행렬, 전단 변환 행렬을 설계해보자.
크기 변환 행렬
표준 기저 벡터 $e_1$과 $e_2$가 있다고 했을 때, 각각을 $a$배, $b$배한 기저 벡터는 다음과 같다.
$e_1’ = (a,\; 0) ,\quad e_2’ = (0,\; b)$
이를 정방행렬로 구성하면 회전 변환 행렬은 다음과 같이 만들어진다.
$S(Scale) = \begin{bmatrix} a & 0 \newline 0 & b\end{bmatrix}$
회전 변환 행렬
표준 기저 벡터 $e_1$과 $e_2$를 $\theta$만큼 회전한 기저 벡터는 다음과 같음을 확인했다.
$e_1’ = (cos\theta ,\; sin\theta) ,\quad e_2’ = (-sin\theta ,\; cos\theta)$
이를 정방행렬로 구성하면 회전 변환 행렬은 다음과 같이 만들어진다.
$R(Rotation) = \begin{bmatrix} cos\theta & -sin\theta \newline sin\theta & cos\theta \end{bmatrix}$
전단 변환 행렬
전단 변환이란 $y$축을 고정시킨 채 $x$축으로 미는 연산이다.
따라서 $e_1$과 $e_2$는 다음과 같이 변화한다.
$e_1’ = (1 ,\; 0) ,\quad e_2’ = (a ,\; 1)$
이를 정방행렬로 구성하면 전단 변환 행렬은 다음과 같이 만들어진다.
$S(Shearing) = \begin{bmatrix} 1 & a \newline 0 & 1\end{bmatrix}$
역행렬
함수에서는 항등함수와 역함수가 존재한다.
선형 변환은 합성 함수와 동일한 개념이다. 그래서 행렬도 항등행렬과 역행렬이 존재한다.
항등행렬은 원공간의 변화없이 공간을 유지하는 변환을 말한다.
표준 기저 벡터의 변환 결과는 다시 표준 기저 벡터와 일치한다.
$I = \begin{bmatrix} 1 & 0 \newline 0 & 1\end{bmatrix}$
그리고 행렬 곱의 결과가 항등행렬이 나오는 행렬을 역행렬이라고 한다.
역행렬은 다음을 만족한다.
$A \cdot A^{-1} = A^{-1} \cdot A = I$
역행렬은 선형 변환된 벡터를 다시 기존의 원공간으로 되돌리는 변환이다.
예를 들어 $I$에서 $A$ 변환을 거치고 $A^{-1}$를 거치면 다시 $I$로 돌아온다.
행렬식
함수가 역함수를 가지기 위한 조건은 함수가 전단사 함수여야만 했다.
행렬도 역행렬을 가지기 위해서는 두 공간의 변환이 전단사로 대응되어야만 한다.
전단사로 대응되는지 확인하는 방법이 행렬식을 이용하는 방법이다.
행렬식은 $det()$ 기호로 정의하며 다음과 같이 계산한다.
$A = \begin{bmatrix} a & b \newline c & d \end{bmatrix}$
$det(A) = ad - bc$
행렬식의 값이 0인 선형 변환은 전단사 대응이 성립하지 않아 역행렬을 가질 수 없다.
예를 들어 행렬 $A = \begin{bmatrix} 2 & 1 \newline 1 & 0.5\end{bmatrix}$ 라고 할 때 행렬식은 다음과 같다.
$det(A) = 2 \cdot 0.5 - 1 \cdot 1 = 0$
평면을 구성하던 표준 기저 벡터들이 $A$ 선형 변환을 거치고 나면 하나의 직선 위에 위치하게 된다.
이를 보고 2차원 평면이 1차원 직선으로 압축되었다고 한다.
축 하나를 잃어버리는 꼴이기 때문에 다시 2차원 평면으로 되돌아갈 수 없다.
변환된 두 벡터가 이루는 평행사변형의 넓이를 살펴보자.
평행사변형이 이루는 넓이 $Area(P)$는 $ad - bc$로 계산된다. 이는 행렬식과 동일하다.
행렬식이 0이라는 것은 평행사변형이 0이라는 것이고 기저 벡터가 구성한 공간이 없어졌음을 알 수 있다.
또 행렬식이 음수라는 것은 평행사변형이 반전된 꼴이다. 즉, 뒤집힌 공간이 만들어짐을 유추할 수 있다.
역행렬의 설계
앞서 설계했던 크기 변환 행렬, 회전 변환 행렬, 전단 변환 행렬의 역행렬을 설계해보자.
크기 변환 행렬의 역행렬
크기 변환 행렬을 통해서 기저 벡터는 다음과 같이 변환된다.
$e_1’ = (a ,\; 0) ,\quad e_2’ = (0,\; b)$
다시 $e_1’$과 $e_2’$를 표준 기저 벡터로 돌려놓기 위해서는 역수를 곱해야 한다.
따라서 역행렬을 다음과 같이 설계할 수 있다.
$S^{-1} = \begin{bmatrix} \cfrac{1}{a} & 0 \newline 0 &\cfrac{1}{b}\end{bmatrix}$
회전변환 행렬의 역행렬
회전 변환 행렬을 통해서 기저 벡터는 다음과 같이 변환된다.
$e_1’ = (cos\theta ,\; sin\theta) ,\quad e_2’ = (-sin\theta ,\; cos\theta)$
다시 $e_1’$과 $e_2’$를 표준 기저 벡터로 돌려놓기 위해서는 $-\theta$만큼 회전시켜야 한다.
$cos(-\theta) = cos\theta$
$sin(-\theta) = -sin\theta$
따라서 역행렬을 다음과 같이 설계할 수 있다.
$R(Rotation) = \begin{bmatrix} cos\theta & sin\theta \newline -sin\theta & cos\theta \end{bmatrix}$
전단 변환 행렬의 역행렬
전단 변환 행렬을 통해서 기저 벡터는 다음과 같이 변환된다.
$e_1’ = (1 ,\; 0) ,\quad e_2’ = (a ,\; 1)$
다시 $e_2’$를 표준 기저 벡터로 돌려놓기 위해서는 다시 반대 방향으로 밀어야 한다.
따라서 역행렬을 다음과 같이 설계할 수 있다.
$S^{-1} = \begin{bmatrix} 1 & -a \newline 0 & 1 \end{bmatrix}$
합성 함수의 역함수에 대해서 다음과 같은 수식이 성립한다.
$(g \circ f)^{-1} = f^{-1} \circ g^{-1}$
두 행렬 곱의 역행렬도 다음과 같은 수식이 성립한다.
$(A \cdot B)^{-1} = B^{-1} \cdot A^{-1}$
마무리
행렬은 그래픽 연산에 있어서 연산량을 줄여주는 도구다.
이를 통해서 실시간으로 반응하는 게임을 제작하는 데 있어 효율적으로 렌더링할 수 있다.
행렬을 설계하면서 트랜스폼을 구성하는 요소 중 크기와 회전에 대해서 설계를 했다.
하지만 이동 대신 전단에 대해서 공부한 것은 의아할 수 있다.
안타깝게도 이동 변환은 2차원에서는 불가능하다. 하지만 이를 우회할 수 있는 방법이 있다.
이를 위해서 전단 변환을 공부한 것이며 이는 나중에 살펴보도록 하겠다.
