MathJax

2014년 2월 4일 화요일

직교 투영 (Orthographic Projection)

이 투영 방법은 z값에 상관없이 변환 후에도 x, y값이 그대로 보존 된다.

원근 투영과 달리 투영 평면에 수직한 평행선을 따라
양의 z값, 음의 z값 모두 같은 평면으로 투영하게 된다.

그래서 특정 구간으로 z값을 제한 하여 사용한다.

투영은 뷰 변환 후에 (l, r, b, t, n, f)의 AABB 공간을 변환하게 된다.
l: 왼쪽 좌표
r: 오른쪽 좌표
b: 아래쪽 좌표
t: 위쪽 좌표
n: 가까운 평면
f: 먼 평면

위 4개 항목(l, r, b, t)는 현재 화면 크기에 맞추어 사용하게 된다.

예를 들어 1024x768의 화면을 가진 프로그램의 경우
(0, 1024, 0, 768)이 된다.

혹은 특별한 상황에 따라 값을 다르게 사용할 수 있다.

투영 변환 후에 생성 되는 공간을 정규화된 장치 좌표.
NDC(Normalized Device Coordinates)라고 한다.

NDC는
최소값으로 (-1, -1, -1), 최대값으로 (1, 1, 1)을 가진
축에 정렬된 정육면체 공간이 된다.

















위의 경우는 OpenGL의 경우이며,

DirectX의 경우는
최소값으로 (-1, -1, 0), 최대값으로 (1, 1, 1)을 가지는
정육면체 공간을 사용한다.


















즉, 직교 투영은 (l, r, b, t, n, f)의 AABB를
(-1, -1, -1), (1, 1, 1)의 AABB로 변환하는 결과가 된다.

먼저 y값의 변환을 생각해 보자.

z값은 y값에 영향을 주지 않으니 y의 변환만 신경쓰면 된다.

첫번째로 y값을 뷰 윈도우(l, r, b, t) 기준으로 되도록
값을 조정(이동) 한다.
아래 점이 원점이 되도록 y값을 수정 하면 다음 같이 된다.





 




두번째로 y값을 NDC영역인 [-1, 1]의 범위가 되도록 조정(스케일) 한다.

[b, t]에서 [-1, 1]으로 변환이 되므로
(t-b)의 크기에서 2의 크기로 스케일 된다.
그래서 다음 크기 만큼 곱해준다.

 










x값도 위와 같은 방법으로 [l, r]범위에서 [-1, 1]범위로 변환하게 된다.

z값의 경우는 추가 작업이 필요하다.

상식적으로 z값은 가까운 평면(n) < 먼 평면(f) 으로 생각 된다.

하지만 OpenGL의 경우 z축은 화면에서 밖으로 튀어나오는 방향이다.

그러므로 실제 계산에서는 z값에 음수를 곱하여 사용해야 한다.

지금까지의 결과로 직교 투영 변환은 이동 변환, 크기 변환이 차례대로
이루어지는 것을 확인할 수 있다.

행렬을 사용하여 차례대로 정리하면
















DirectX의 경우 NDC의 z값은 [0, 1]범위가 된다.
[n, f]에서 [0, 1]으로 변환이 되므로 (f-n)의 크기에서 1의 크기로 스케일 한다.
n의 값이 ndc로 변환했을때 원점이 되므로 이동 변환할때는
현재 z값에서 n값 만큼만 빼주면 된다.

그리고 z축은 화면 밖에서 안쪽으로 들어가는 방향이 되므로 z값에 음수를 곱하지 않아도 된다.











그 결과 위의 행렬은 조금 수정되어 아래와 같이 된다.

















참고자료
Essential Mathematics For Games And Interactive Applications
Real-Time Rendering 2판

댓글 없음:

댓글 쓰기