본문 바로가기
기타 개발 관련/3D 그래픽스

그래픽스 - Projection Matrix란?

by 번데기 개발자 2018. 7. 15.
반응형


투영행렬과 뷰행렬의 관계


뷰 행렬(View Matrix)란 랜더링 파이프라인 단계의 3번째 단계인 뷰 스페이스를 구성하는데 사용되는 설정을 위한 행렬이라고 한다면

투영 행렬은 파이프라인 단계의 투영 과정시에 이루어지는 작업을 위한 정보를 준비하는 것입니다.


투영 과정은 사실상 뷰 스페이스와는 별개의 과정이지만, 눈에 보이는 화면의 시점을 결정하는 성질을 가지므로, 카메라 객체과 뷰행렬과 함께 투영행렬을 함께 관리하도록 구성하기도 합니다.






X,Y,Z로 3개의 정보로 이루어진 3차원 공간을 X,Y 좌표만으로 표현한다고 생각하면 조금 쉽게 이해할 수 있습니다.

이것은 2차원 면 위에 입체 도형을 표현하는 과정입니다.



투영이란 무엇일까?


투영(Projection) 이라는 것은 n차원의 공간을 n-1차원으로 표현하는 것을 의미합니다.

보통은 3차원 공간을 2차원으로 표현할 때 많이 사용합니다.

즉 (0,0,0) 과 같은 식으로 구성된 3차원 좌표계를 2차원의 (0, 0) X,Y 좌표만으로 표현하는 것을 의미합니다.


이런식의 과정이 필요한 이유는 보통 3차원을 접하는 매체가 2차원인 액정 화면이기 때문입니다.

가상의 3차원 공간을 최종적으로 모니터에 출력할 수 있도록 2차원으로 가공하는 처리를 해준다고 볼 수 있습니다.




3차원 좌표를 2차원 좌표로 바꾸기 (개념)


 





위의 과정이 어떻게 이루어지는지 살펴보겠습니다.


3차원을 2차원으로 바꾼다는 것은 결국 X,Y만으로 표현을 하겠다는 의미입니다. 

하지만 그렇다고 해서 기존에 가지고 있던 Z값을 완전히 배제하면 입체감을 표현할 수 없습니다.


따라서 기존의 Z값을 활용하는 방향으로 작업하게되는데, 이때 사용되는 개념이 Z를 시야로부터의 거리로 삼아 정점의 X,Y 좌표를 거리에 비례하여 수정하는 작업입니다.


X를 예로 들면, 거리가 멀어질수록 양의 좌표계에서 기존의 X에서 감소를 시키는 처리를 하고, 음의 좌표계에서는 기존 X에서 증가시키는 처리를 하고, 최종적으로는 0으로 수렴하게 됩니다.

이것은 미술에서 흔히 사용되는 소실점 개념 중 하나인 1점 투시도법과 같은 느낌을 줍니다.









소실점 개념을 적용하여 3차원에서 2차원으로 좌표 변환하기 (행렬)



가정을 한번 해보겠습니다.

  • 윈도우 창은 X,Y 좌표만 가진 2차원의 좌표계입니다.
  • 따라서 기준의 3차원 좌표를 2차원 좌표로 변환하는데, 이때 Z값은 거리인 것으로 판단합니다.
  • X,Y 좌표에 소실점 개념을 도입하여 거리가 멀어질수록 이에 비례하여 보정 연산을 한 뒤 입체감을 나타내는 방향으로 가야합니다.



이렇게 구해진 좌표계는 어디까지나 기존의 월드 좌표계와는 별개의 좌표계가 구성됩니다.

월드 좌표계가 3차원 좌표계였다면, 투영되어 새로 만들어지는 좌표계는 이 정보를 반영하기만 하였을뿐, 2차원으로 구성된 별개의 좌표계가 되는 것입니다.





Direct 환경에서의 투영 행렬 구성


실제로 2차원으로 변환과정을 거치는 것은 디바이스에서 내부적으로 이루어 집니다.

때문에 투영 행렬을 만드는 것은 직접적인 2차원 좌표를 구하기 위한 정보를 전달하는 것이 아닙니다.


Direct 또는 OpenGL 환경에서는 2차원 변환을 거치기 이전에, 투영할 대상이 되는 정점들을, (-1, -1, 0) ~ (1, 1, 1) 의 범위를 가진 공간속에 변환하여 옮겨넣는 작업을 먼저 합니다.

Z 를 0~1  이라는 범위로 한정시키는 것으로 2차원 변환을 위한 사전 작업을 하는 셈입니다.

좀 더 풀어서 말하면, Z를 0 ~ 1 에 한정시켜서, 비율에 따른 X, Y 변환을 유도하는 것입니다.


( 여기서 Z가 0인 평면을 Near, Z가 1인 평면을 Far이라고 지칭하게 됩니다. )


X,Y 는 -1 ~ 1 의 범위로 변환되며, 음수 범위를 두는 이유는 소실점이 되는 원점을 중앙으로 고정시키기에 용이하기 떄문입니다.


떄문에 디바이스에 넘겨줄 투영 행렬은 X, Y, Z 좌표를 모두 변환시키는 행렬입니다.

다만 Z 좌표는 무조건 0 에서 1로 구성되도록 만들어야 합니다.





투영행렬은 이런식으로 구성됩니다.



투영 행렬 구성 분석하기



위에 식을 좀더 분석해보겠습니다.

W, H는 X, Y 의 값을 변형시키는 역활을 하고, 여기서의 X,Y의 기준은 Fov 시야각에 따를 비율이 필요합니다.

Fov는 밑에서 설명하겠습니다.



Z 값을 조절하는 A, B 값은 투영 공간 속에 표현될 Z의 비율을 구하는 역활을 해줍니다.

여기서 구체적인 값을 구해낼때는 Near평면의 Z가 0이고 Far 평면의 Z가 1이라는 점을 사용합니다.



따라서,

Near 평면은 연산하는 경우는 

  • aZ + b =0

Far 평면을 연산하는 경우는

  • aZ  + b =1

과 같은 식으로 식을 2개 세우고 이들의 연립방정식을 계산하게 됩니다.

그 이후 구체적으로 행렬에 넣을 값을 유도하게 됩니다.

하지만 이 식만으로는 정확한 a, b값을 유도하기 어렵기 때문에 최종적으로 다른 식을 사용합니다.





다음으로 구성할 것은 W 와 H 의 값입니다.

이 값은 시야 각도인 Fov 각도에 따라 구성된 직각 삼격형의 비율에 따라 결정됩니다.




FOV란 무엇일까?


화면에 표현할 시야의 각도를 표현하는 것으로, 구체적으로는 보여줄 각도만큼 투영시킬 화면의 범위를 넓혀주는 것으로 생각할 수 있습니다.

이를테면 동일한 윈도우 창에 투영 결과를 출력할 때에도 , Fov의 각도에 따라서 보다 넓거나 좁은 범위를 표현하거나, 각도와 거리에 따라서 거리감을 표현하는 등의 역활을 해줍니다.


여러 게임 등에서도 Fov 값을 게임 속에서 변경할 수 있는 옵션을 제공하기도 하는 등 Fov 값은 시야각을 표현하는 대부분의 작업에 활용됩니다.







시야각은 시야 범위에 따라서 달라지게 됩니다. 

각도가 넓을수록 표현 범위가 넓어지게 됩니다.

하지만 동시에 거리감도 달라지기 때문에 적절한 시야각을 찾아야 합니다.



 





실제로 Fov 각을 변경하여 이를 투영 과정에 반영한 결과입니다.

각도를 넓게 설정한 경우 더 넓은 시야 범위를 제공하는 것을 확인할 수 있습니다.




Fov를 이용한 투영행렬 연산


위에서 살펴본 Fov 각도를 투영 행렬의 인자로 반영하는 것과 연관지어 생각해 봅시다.



시야 범위를 표현할 각도가 있고 이를 투영 연산에 반영할 수 있도록 만드는 작업이 필요합니다.

그렇지만 현재 알고있는 정보는 어디까지나  "시야를 표현할 각도" 가 전부입니다.



이 각도에 따라서, 3D 월드 정점의 X, Y 값을 변경하여 시야에 따라서 표현되는 범위가 조절되는 것처럼 보이도록 만드는 작업이 현재 필요한 작업입니다.

때문에 현재 가진 정보인 각도로, 정점 연산을 위한 비율을 구해는 과정을 알아보겠습니다.







이같은 연산으로 구성된 w와 h의 값을 투영 행렬의 인자로 넣겠습니다.




* 내가 생각한 부분

: near 와 far을 만약에 1, 1000으로 준다면 zn =1 zf =1000으로 두고 계산한다.

: wX, wY에서 w값은 cot(fov/2) 에 의해 계산한다.

: 맨 마지막에 [wX,wY, aZ + B, Z]에서 aZ +B가 비율이며 이 값은 0~1 사이이다.

: wX, wY를 aZ + B의 값에 의해 변환시킨다. 아마 곱셈연산을 할것으로 추정됨...

: 그렇다면 최종결과는 [-1 ~+1 사이, -1 ~+1 사이, 0 ~1 사이, Z ] 이렇게 변하게 된다.











반응형