3D 공간을 나타내는 화면상의 어느 한 점을 표현하기 위해서는 물체의 Local 좌표를 카메라를 기준으로 하는 화면 좌표로 변환해야 하는 과정이 필요합니다. 이러한 작업을 '투영(Projection)'이라고 합니다. 즉, 투영을 하기 위해서 우리가 사용하는 좌표를 변환하는 과정이 필요하다는 의미입니다.
처음으로 물체는 로컬 공간(Local Space)에 정의 되어있다. 로컬 공간에 정의된 물체는 월드 변환을 통해서 월드 공간(World Space)로 이동합니다. 이 월드 공간에 렌더링할 대상의 물체들과 카메라, 광원 등이 배치됩니다. 다음으로는 카메라 행렬에 의해서 뷰 공간(View Space)로 변환됩니다. 이 변환을 통해서 카메라를 기준으로 하여 새로운 좌표체계가 완성되게 됩니다.
이제 이 카메라를 통해서 화면 공간(Screen Space)에 물체를 표현해야 하기 때문에 3차원 공간(화면 공간)을 2차원 공간(화면 공간)으로 변환해야하는 과정이 필요합니다. 이 과정을 투영 변환이라고 합니다.
왼쪽의 그림은 카메라 좌표계의 XZ 평면을 나타내며, 이 상태에서 투영변환 된 것이 오른쪽의 XZ 평면이다. 왼쪽 그림의 원점에 카메라가 존재하고, 카메라가 비출수 있는 공간이 빨간 선이 둘러진 부분입니다. 카메라의 표현이 가능한 공간은 유한하며, 왼쪽 그림의 두 평면 (Near, Far)의 공간 사이의 물체만 화면에 나타나게 됩니다. 왼쪽 그림의 빨간색 부분이 화면을 표현하는 공간인 절두체(Frustrum) 영역입니다. 투영 변환은 이 절두체 영역을 오른쪽 그림과 같은 공간으로 변환하는 것을 의미합니다.
먼저 투영행렬을 유도하기 위해서는 카메라 좌표계를 구성하는 각 성분에 대해서 이해가 필요합니다. 카메라가 표현하는 공간까지의 거리인 d의 값을 알아야 합니다. 이 값을 구하기 위해서, 카메라의 시야각(FOV)을 이용합니다. 삼각함수를 이용하여 tan의 값을 구할 수 있는데, 그 값은 다음과 같습니다.
이 식을 d로 정리를 하면, d는 다음과 같습니다.
이제 다시, 처음의 그림으로 돌아가서, 공간상의 점을 화면에 표현을 할수 있도록 해봅니다.
절두체 내부의 모든 점들은 투영 평면((1, d) ~ (-1, d)) 위에 표현됩니다. 두 점과, 삼각형의 닮은꼴을 이용하여 투영 평면 위에 표현되는 모든 점들을 찾아낼 수 있습니다. 즉 투영 평면 상의 점 P의 y 성분의 값은 다음 비를 만족합니다. 또한, 오른손 좌표계에 의해서 Pview의 Z값은 -Zview값이 됩니다.
이 비율을 이용하여 Yndc값은 다음과 같이 나타나게 됩니다.
똑같은 방법으로 XZ 평면상의 점또한, 다음 비를 만족할 것입니다.
이 비율을 이용하여 Xndc의 값은 다음과 같이 나타나게 됩니다.
그러나, 이경우는 투영평면이 정사각형으로 표현되는 경우 나타나게 되는 경우이며, 일반적인 화면의 비는 가로가 더 넓기 때문에, 종횡비 a의 역수를 Xndc의 성분에 곱해주게 되면 투영 평면 위의 점을 구할 수 있습니다.
최종적인 투영변환 공식은 다음과 같습니다.
이제, 뷰 공간의 점을 화면 공간의 점으로 선형 변환하는 행렬이 있다고 가정합니다.
.
그러나 Xndc와 Yndc의 값은 구했으므로, 위의 행렬은 다음과 같이 표현이 가능합니다.
여기에서, W'의 값이 Zview의 값과 같다고 가정하게 되면, 점의 정의가 동차 좌표계의 정의와 일치하게 되며, Zview값을 모두 바꿀 수 있게 됩니다. 즉 행렬식을 변경하면 다음과 같게 됩니다.
이제 마지막으로 k와 l의 값을 구하는 일이 남았습니다. 두개의 미지수는 근평면(Near Plane)의 거리와 원평면(Far Plane)의 거리를 이용하여 다음과 같은 행렬식을 유도할 수 있습니다.
각각의 행렬에서 다음과 같은 식을 알 수 있습니다.
두 식을 연립방적식을 통하여 구하면 k와 l의 값은 다음과 같습니다
최종적으로 우리가 구하는 투영 행렬은 다음과 같게 됩니다.
'게임 수학' 카테고리의 다른 글
삼각형 빠르게 칠하기(Flat Shading) (0) | 2019.12.17 |
---|---|
NDC(Clip Space)란 무엇인가? (0) | 2019.12.17 |
백페이스 컬링 (0) | 2019.12.17 |
벡터 내적과 외적을 응용한 왼쪽과 오른쪽의 판별 (0) | 2019.12.17 |
내적을 사용한 시야 판별 (0) | 2019.12.17 |