게임수학/행렬

게임수학) Chapter6. World,View,Projection,Screen 행렬 (3)

PJNull 2021. 11. 29.
728x90
반응형

 

XMMATRIX XM_CALLCONV XMMatrixLookAtLH(
FXMVECTOR EyePosition, 
FXMVECTOR FocusPosition, 
FXMVECTOR UpDirection);

//EyePosition:카메라의 월드 기준의 좌표
//FocusPosition:카메라가 주시하고 있는 점
//UpDirection:대략적인 Up벡터 통상적으로 <0.0f,1.0f,0.0f>를 넣는다
//리턴값:World Space에서 View Space로 변환해줌

 

그림과 같이 EyePos,FocusPos,UpDirection를 넣어주면 이것들이 만들어내는 사각형과 직교인 Right벡터를 추출해 낼수있다. 또한 구한 Right 벡터와 Look벡터를 통해 실제적인 UP벡터를 구함으로써 View Space를 반환해줄수 있다.

 

 

 

 

Projection Space(원근투영)

 

z:y=1:y'를 성립해야한다. 이식에서 y'=y/z가 성립하며 이것은 x도 마찬가지이므로 x'=x/z를 성립해야한다.

최종적으로 우리의 스크린사이즈에 맞는 비율(800x600 or 1920x1080)처리를 해주어야한다.하지만 화면에 맞추어 대상을 늘리게되면 정사각형이 직사각형이 되어버리는 현상이 일어난다.

이럴때 미리 화면비율을 나누어서 그러한 현상을 방지한다. 800x600의 모니터를 기준으로 한다면,

r=w/h=800/600이고

x'=x/(z*r)

y'=y/z가 되게 된다.

또한 임시적으로 카메라의 각도를 90º로 지정했지만 카메라의 각도는 다양하다.

카메라의 임의의 각도를 θ라고 가정하고 밑변이1이라고 한다면 높이는 tan(θ/2)가 된다.

Clip Space는 (-1,-1)~(1,1)의 범위이기 때문에 tan(θ/2)를 1로 보정 시켜줄 필요가 있다.

이것을 처리해주면 다음과 같은 식이 나오게된다.

x'=x/(r*z* tan(θ/2))

y'=y/(z* tan(θ/2))

 

일반적으로 (x,y,z,1)에 곱하여 값을 얻기 위해서는 선형공식이 성립되어야한다.

하지만 위의식을 보면 알 수 있지만 x식에 z가 포함 되어있고 y식에도 z가 포함되어있어 선형공식이 성립되지 않는다.

왜냐하면 z값(Depth)은 일정하지 않기 때문이다.

이를 위해서 일단 z를 제외한 나머지 값들을 정리해줄 필요가 있고 식으로 정리하면,

가 성립하고 여기서 얻은값에서 z를 나누어주면 x와 y값을 얻을수 있게된다.

하지만 z좌표 자리에는 0~1사이의 값을 가져야 하며 z값을 보존할수 없기때문에 w좌표에 z값을 보존하는 방식을 채택할 수 있다.

이것을 행렬로 나타내면,

 

로 표현되는데,z좌표에 올 0~1의값을 A와B라고 가정한다면

와 같은 식이 나오게된다. 이것을 레스터라이즈한테 넘겨주게 되면

w좌표에 보존되어 있는 z값을 나누게된다.

 

 

여기서 z좌표의 값은 Near~Far(0~1)인데 이것을 함수로 표현하면

로 표현될수 있고 두가지 식에서

라는 결론을 얻을수 있으며 결론적으로

 

라는 행렬을 얻을수 있다.

 

 

 

 

Screen Space(Viewport)

 

Viewport로 변환을 할때에는 전체화면이 아닌 임의의 일부 영역에 그려준다는 가정을 한다.

 View Space의 임의의 점을 x라고 가정한다면 x는 (-1~1)이므로 전체길이가 2이며 x는 x+1의 길이를 가지게 되며,

Viewport에서의 X값은 X=Left+(x+1)/2의 값을 가지게 되며 해상도에 따른 비율을 곱해주면 된다.

마찬가지로 y값은 (1~-1)의 범위를 가지며 Y=Top+(1-y)/2가 되며 해상도에 따른 비율을 곱해주면된다.

이것을 정리하면 아래와 같은 식이 나오게 된다.

이것을 행렬식으로 변환하면

가 나온다.

 

보통의 Depth값은 0~1으로 사용하지만 경우에 따라선 임의의 MinDepth/MaxDepth값으로 사용할수도 있다.

(단, 범위는 동일하게 0~1)

이렇게 임의의 Depth값을 이용하는 이유는 다수의 Viewport를 생성할때 Viewport간의 Depth차가 나오게 할 수 있기 때문이다.

이것을 식으로 표현하면 Z=Min+Z(MaxDepth-MinDepth)라는 식이나오고,

결론적으로 아래와 같은 행렬식이 나오게 된다.

728x90
반응형

댓글