2016년 5월 26일 목요일

공간 변환: 투영 행렬 정리

공간 변환


Object Space(Local Space or Model Space) : 물체가 기준인 공간

World Space : 모든 물체가 공유하는 공간. 실제 세상 공간.

View Space(Camera Space) : 카메라가 세상의 중심인 공간. 카메라 기준으로 World를 바라본 공간.

Projection Space : View Space를 투영한 공간. x, y는 -1~1까지의 좌표를, z는 0~1까지의 좌표를 가짐.

Screen Space : 화면 공간. 왼쪽 상단이 (0, 0)으로 시작하여 (w-1, h-1)까지의 좌표를 가짐.


Local Space -> World Space


물체가 중심인 세상에서 월드 공간으로 나온다는 것은
크기(Scale), 회전(Rotation), 이동(Translation)
즉 W=SRT라고 할 수 있고 행렬은 다음과 같다


World Space -> Camera Space


월드 공간에서 어느 하나의 오브젝트가 중심인 공간으로 공간 변환을 한다는 것은 World Space에서 해당 오브젝트의 Local Space로 이동하는 것과 같다.

다시 말해, World Marix는 해당 오브젝트가 세상에 나오기 위한 행렬이었으므로, 특정 오브젝트가 중심인 공간으로 변환한다는 것은 해당 오브젝트의 World Matrix의 역 행렬을 사용하면 된다.

그래서 카메라가 중심인 Local Space에서 World Space로 나오기 위한 행렬 W의 역 행렬을 구하면 그 행렬이 카메라가 중심인 공간(Camera Space)으로의 변환 행렬을 뜻한다고 할 수 있다.

또한 World Space와 Camera Space는 동일 공간상의 변환이므로 크기 변환은 제외되어 있다고 할 수 있다. 즉 W=SRT 이므로, W=RT로 생각해볼 수 있으며, 그 역행렬은 W-1 = T-1R-1으로 표현 가능하다.


Camera Space -> Projection Space


FOV(field of view) : 시야각

Aspect Ratio(종횡비) : screen width/ screen height

Projection Window는 Near Plane과 Far Plane과 동일한 비율을 가지므로 실제 크기는 중요치 않다.

그래서 Near Plane과 Projection Window를 동일하게 보는 경우가 많다.

그런 이유로 r(=width/height)을 구할 때 실제 크기보다 비율이 중요하므로 height를 2로 하여(위/아래 각각 1) 단순화 시켜서 계산하도록 한다.






d와 r이 구해지면 β를 구할 수 있다. 식의 r에 의해 β는 계속 변화한다.


3차원 공간상의 점 (x, y, z)를 투영공간에 변환한 점 (x', y', z')은 비례값에 의해 
라고 할 수 있으므로, 다음의 식이 성립한다.


y값 또한 마찬가지로 x의 위치에 대신 올 수 있다.

이렇게 구한 값에 따라

x'는 -r <= x' <= r
y'는 -1 <= y' <= 1
z는 n <= z' <= f

일 때 절두체 내부에 있다고 할 수 있다.

앞선 방식은 r에 의해 x', y'의 값이 좌우된다. 즉 하드웨어에서 계산을 하기 위해서 항사 r(Aspect ratio)를 필요로 한다는 문제가 생긴다.

이를 단순화 하기 위해 NDC(Normalized Device Coordinates) 좌표로 변환을 한다.
x'와  y'에 대해서 r로 나누는 것이다.

이를 통해 범위는 다음으로 조정 가능하다.
r로 나눈 값에 의해 x'는 NDC 좌표계에서 다음과 같이 표현 가능하다.
x, y는 선형 연산이 가능하나 z는 선형 변환이 되지 않는다.(z로 나누어 투영을 처리하기 때문)
그래서 z 나누는 연산을 나중으로 미뤄두고 선형행렬을 구성한다.



z축 값에는 x, y의 값이 없으므로 0.
A, B는 무슨 값이 들어갈지 모르므로 상수 A, B를 설정

나중에 z로 나누기 위해서는 z값이 존재해야 하는데 동차 좌표상의 w값에 이 값을 잠시 복사해두면 된다. 
그래서 3행 4열 성분과 4행 4열 성분을 각각 1과 0으로 설정

계산의 편의를 위해 각 성분에 z를 곱해버린다.


최종적으로 구해진 (zx', zy', zz', z)를 w 값인 z로 나누면 다음과 같다.


투영된 z의 값(=z')은 0~1의 범위를 가져야 한다. (깊이 테스트를 위한 것)
이를 위해 구해진 다음의 식을 풀어야 한다.
z에 0과 1을 대입하여 B에 대해서 풀면 B = -An이 나오고 이에 따라 식을 풀면 다음과 같다.



이제 앞서 구해놓은 투영 행렬에 새로 구한 A, B의 값을 채운다.

이렇게 구해진 z의 값은 다음과 같은 그래프 모양으로 나타난다. 카메라에서의 거리가 가까울수록 깊이에 대한 묘사가 섬세해진다.


댓글 없음:

댓글 쓰기