본문 바로가기
DirectX/[Inflearn_rookiss] Part2: DirectX12

12. Projection, Screen 변환 행렬

by 헛둘이 2023. 1. 23.

투영 변환이란?

- View 좌표계를 Projection 좌표계(NDC)로 변환하는 것

- 원근투영, 직교투영이 있으며 원근투영을 주로 사용

 

원근투영의 예시

 

 

Near과 Far의 개념

 

near과 fat는 z축에 위치하며,

그 사이 범위의 z값을 가진 물체들을 카메라로 표현한다

 

- 카메라 각도는 FOV(Field Of View), 화각이라고도 불린다.

- 유니티 엔진에서는 이 화각을 변경할 수 있다.

- 투영 좌표계에서는 모든 것을 비율로 생각한다.

- Z값, 즉 얼마나 카메라에서 멀리 떨어져있냐가 관건

 

카메라 각도가 90도라면?

 

X = X/Z

Y = Y/Z

 

비례식에 따라 Z값을 X, Y 각각에 나눠주면 된다.

 

1:a = 2:b

- a는 알 수 있으므로 비례식을 통해 b도 구할 수 있다.

 

그대로 늘리면?

- NDC 좌표계의 정사각형 물체를 800x600 화면으로 늘리면 직사각형이 된다.

- 이를 보정해주기 위해 한 쪽에 ratio를 구해서 곱해준다

- ratio = width / height

 

 

카메라가 90도가 아니라면?

- 영역이 커지면 90도를 찍고 있는 것마냥 보정해주면 된다.

 

- 밑변이 1이므로 높이는 tan𝜽/2가 된다.

- 그러므로 z로 나눠주는 것이 아닌 tan𝜽/2로 나눠주면 변환된 비율이 나오게 된다.

- 식을 정리하면

 

- 이렇게 정리할 수 있는데,- 하나의 행렬으로 메쉬를 처리할 수 없다는 문제에 봉착- 사람 머리 같이 둥근 형태의 메쉬의 경우 z 값이 각기 다르기 때문- 따라서 z는 지금 처리할 수 없으니 그냥 그대로 나오도록 행렬식을 만들어야 한다.

 

- 이 행렬식을 거친 벡터 (x, y, z, 1)은 아래와 같이 계산된다.

-

 

- 이 값을 z를 이용해서 나눠주면 되는데, - 이러면 z축을 깊이 테스트에 z(0~1 사이 값)를 사용할 수 없게 된다.- 그래서 지금 사용하지 않는 w값에 z를 저장해서 그 값으로 나눠주는 방법을 생각해볼 수 있다.- 그러면 이제 z를 어떻게 0~1로 둘 것이냐가 관건인데- 아래와 같이 행렬을 구성해서 A, B라는 임시변수를 둬서 A, B를 통한 계산을 생각해볼 수 있다.

 

- 이 행렬을 거친 벡터는 아래와 같이 구성이 된다.

 

- 이제 모든 요소를 z로 나눠주면

 

- 이렇게 식이 구성이 된다.

- 그러면 A + B/z가 어떤 값을 가져야 할지 유추할 수 있는 함수식을 세울 수 있다.

- Z가 Near일 때는 0, Far일 때는 1이여야 하므로,

- 아래와 같이 식을 세울 수 있고,

- 식을 정리하면 아래와 같이 정리된다.

 


스크린 변환이란?

-NDC 좌표계의 좌표를 실제 해상도의 Viewport에 출력하기 위한 좌표 변환

 

Viewport는?

- 실제 렌더링할 사각 영역

- 전체 화면의 일부를 Viewport라고 한다.

- Viewport의 좌상단을 (Left, Top)으로 잡는다면

 

X = Left + (x + 1 / 2)

 

x + 1 /2를 해주는 이유는?
-1 <= x <= 1인 좌표계에서
-1 + 1 <= x + 1 <= 1 + 1
0 <= x + 1 <= 2가 되고, 여기서 2로 나눠주면
0 <= (x + 1)/ 2 <= 1이 된다

 

y도 동일한건가?
y는 좌표계가 반대로 되어 있으므로
1 <= y <= -1인 상태에서 원상복구하려면

1 - 1 <= 1 - y <= 1 - (-1)
0 <= 1 - y <= 2이므로, 2로 나눠주면
0 <= (1 -y)/2 <= 1가 된다

 

행렬로 나타내면

 

 

maxd와 mind는 해당 Viewport의 최대 깊이와 최소 깊이를 나타낸다.

댓글