비타Cpp

렌더링 파이프 라인 - VS(Vertex Shader) Stage - 투영과 동차 절단 공간 본문

DirectX12/메모

렌더링 파이프 라인 - VS(Vertex Shader) Stage - 투영과 동차 절단 공간

멍C 2021. 8. 6. 12:41

카메라의 요소에는 위치와 방향만 있는 것이 아니다. 바로 카메라에 보이는 공간, 바로 절 두체(Frustum; 각뿔대, 끝이 잘린 사각뿔)에 대해 정의해야 한다.

 

3차원 장면을 2차원의 이미지로 표현하려면, 절두체 안에 있는 3차원 기하구조를 2차원 투영 창으로 투영해야 한다. 이때 3차원의 요소를 2차원의 투영 이미지에서 표현하는 방법 중 하나는 바로 "원근감"이다. 

 

원근감을 나타내기 위해서는 투영을 하나의 소실점을 만들어서 절두체 모양으로 해야 하는데, 이때의 투영을 원근 투영(Perspective Projection)이다. 원근 투영은 아래 그림처럼 표현된다.

 

3차원 기하구조의 한 정점에서 시점(Eye Point)으로의 직선을 정점의 투영선(line of projection)이라고 한다. 원근 투영 변환은 아래 그림처럼 하나의 3차원 정점 v를 그 투영선이 2차원 투영 평면과 만나는 점 v'으로 변환하는 변환이다.

 

 

이젠 절두체를 정의해본다. View 공간에서 투영의 중심을 원점에 두고 양의 z축을 바라보는 시야 절두체를 네 가지 수를 이용해서 정의할 수 있다. 여기서 사용되는 네 가지 수량은 원점과 가까운 평면 사이의 거리 n, 먼 평면 사이의 거리 f, 수직 시야각 α, 종횡비 r이다. 이는 아래 그림으로 알기 쉽게 표현했다.

 

수직시야각 α와 종횡비 r로 수평시야각 β

 

r의 정의는 투영 창의 넓이 / 투영 차의 높이 (w/h)로 정의된다. 예를 들어, 후면 버퍼가 1920 x 1080이면 r = 1920/1080 ≈ 1.777로 설정한다.

 

편의상 종횡비가 w:h을 가진다고 가정했을 때, r = w/h -> w = hr이 된다.

 

수직 시야각이 α가 되는 투영 창 거리 d는 아래와 같이 구해진다.

 

$$\tan(\frac{\alpha}{2}) = \frac{h/2}{d}\Rightarrow\ d = \cot(\frac{\alpha}{2})h/2$$

 

그다음은 수평 시야각 β를 구하는 식이다.

 

$$\tan(\frac{\beta}{2}) = \frac{r}{d} = \frac{r}{\cot(\frac{\alpha}{2})h/2} = r\ \cdot \ \frac{\tan(\frac{\alpha}{2})}{h/2}$$

 

$$\beta = 2\tan^{-1}(r\cdot \frac {\tan(\frac{\alpha}{2})}{h/2})$$

 

 

위의 그림을 보면, 투영 창의 높이가 2일 때, 점(x, y, z)을 z = d 평면에 투영한 점(x', y', d)을 구하고자 한다. 좌표 성분 x와 y를 따로 고찰하고 닮은꼴 삼각형의 원리를 적용하면,

 

$$\frac{x'}{d}=\frac{x}{z}\Rightarrow \ x' = \frac{xd}{z} = \frac{x \cot(\alpha/2)}{z} = \frac{x}{z \tan(\alpha/2)}$$

 

이고,

 

$$\frac{y'}{d}=\frac{y}{z}\Rightarrow \ y' = \frac{yd}{z} = \frac{y \cot(\alpha/2)}{z} = \frac{y}{z \tan(\alpha/2)}$$

 

임을 알 수 있다. 이때 점(x, y, z)가 절두체 안에 있을 필요충분조건은 다음과 같다.

 

$$-r\leq x' \leq r \\
-1\leq y' \leq 1 \\
n \leq z \leq f$$

 

 

Comments