2.1 직교 카메라
이번 섹션에서는 직교 카메라에 대해 알아보겠습니다. 이전에 우리는 원근 카메라를 살펴보았는데, 이는 먼 객체가 화면에 더 작게 보이는 실제 핀홀 카메라를 모방합니다. 이 원근 효과는 우리의 자연스러운 시각 경험을 반영합니다. 이와 대조적으로, 직교 카메라는 객체가 카메라로부터의 거리에 관계없이 화면에서 객체의 원래 크기를 유지하며, 원근 왜곡을 제거합니다.
플레이그라운드 실행 - 2_01_orthogonal_cameras직교 카메라는 3D API를 사용하여 2D 애플리케이션(예: 이미지 처리 도구)을 만들 때와 같이 다양한 시나리오에서 유용합니다. 이러한 경우 원근 효과로 인한 이미지 왜곡을 피하고자 합니다. 직교 투영은 이러한 상황에서 탁월하며 45도 탑뷰 비디오 게임에서도 자주 사용됩니다.
직교 투영 행렬을 도출해 봅시다. 투영 전에 좌표계를 뷰 좌표로 변환한다는 것을 기억하세요. 이 시스템에서는 xy 평면이 화면 평면과 평행하며, z축은 우리를 향합니다.
3D 장면을 둘러싸는 화면 정렬된 바운딩 박스를 상상해 보세요. 우리의 투영 목표는 이 바운딩 박스를 x, y, z에 대해 [-1,-1,-1]에서 [1,1,1] 범위의 NDC(정규화된 디바이스 좌표)로 매핑하는 것입니다.
이 계산은 원근 투영보다 간단합니다. 화면 좌표의 오른쪽 가장자리를 r, 왼쪽 가장자리를 l이라고 합시다. 뷰 좌표에서 (x,y)에 있는 점 p가 주어지면 다음과 같습니다:
\begin{aligned}
& l \leq x \leq r \\
& 0 \leq x \leq r-l \\
& 0 \leq \frac{x-l}{r-l} \leq 1 \\
& 0 \leq 2 \times \frac{x-l}{r-l} \leq 2 \\
& -1 \leq 2 \times \frac{x-l}{r-l} -1 \leq 1
\end{aligned}
x-좌표를 [-1,1] 범위로 성공적으로 변환했습니다. 이제 계산을 Ax + B 형태로 다듬어 행렬 곱셈으로 표현할 수 있도록 하겠습니다:
\begin{aligned}
& -1 \leq \frac{2x-2l-r+l}{r-l} \leq 1 \\
& -1 \leq \frac{2x}{r-l} - \frac{r+l}{r-l} \leq 1
\end{aligned}
y와 z에 대해서도 유사한 방정식을 도출할 수 있습니다. NDC는 왼손 좌표계를 사용하므로 z축을 뒤집어야 합니다:
\begin{aligned}
x^\prime &= \frac{2x}{r-l} - \frac{r+l}{r-l} \\
y^\prime &= \frac{2y}{t-b} - \frac{t+b}{t-b} \\
z^\prime &= \frac{-2z}{f-n}-\frac{f+n}{f-n}
\end{aligned}
t와 b는 화면 좌표의 상단과 하단이며, n과 f는 근거리 및 원거리 평면입니다. 이제 이러한 계산을 행렬 곱셈으로 표현할 수 있습니다:
\begin{pmatrix}
\frac{2}{r-l} & 0 & 0 & 0 \\
0 & \frac{2}{t-b} & 0 & 0 \\
0 & 0 & \frac{-2}{f-n} & 0 \\
-\frac{r+l}{r-l} & - \frac{t+b}{t-b} & -\frac{f+n}{f-n} & 0
\end{pmatrix}
직교 카메라 구현은 간단합니다. 셰이더 코드와 대부분의 JavaScript 로직은 변경되지 않으므로, 주요 요소에 초점을 맞추겠습니다:
let orthProjMatrix = glMatrix.mat4.ortho(glMatrix.mat4.create(), -320.0, 320.0, 240.0, -240.0, -1000.0, 1000.0);
직교 투영 행렬은 원근 투영 행렬과 매우 유사합니다. glMatrix 라이브러리를 사용하여 이 투영 행렬을 쉽게 생성할 수 있습니다. 뷰포트의 너비와 높이, 그리고 뷰 절두체의 근거리 및 원거리 평면을 지정하여 직교 투영 행렬을 얻습니다.
원근 투영과 달리 직교 투영의 뷰 절두체는 원뿔이 아닌 단순한 3D 직사각형입니다. 나머지 코드는 원근 투영 프로그램과 동일하게 유지됩니다.