센로그

5. Input Assembler & Vertex Processing(2) 본문

게임/그래픽 프로그래밍

5. Input Assembler & Vertex Processing(2)

seeyoun 2023. 5. 12. 19:17

◆ View Frustum

우선 카메라에 관한 이야기를 좀 해보자.

 

카메라는 무한한 공간을 보지 않는다. Fov(Field of View; 시야)가 한정되어 있기 때문.

따라서 우리는 카메라가 어느정도 볼건지를 결정해야 함. View frustum(잘린 피라미드) 안에 있는 애들만 보도록 한다!

여기서 나오는 x, y, z는 world space가 아니라 camera space임. 편의상 u, v, n대신에 x, y, z로 설명

▲directX 기준이므로 -f, -n이 아니라 f, n인듯?

 

4가지 파라미터:

  • fovy(얼마나 넓은 y만큼 볼거냐. 안잘린 피라미드 꼭대기 각도 느낌)
  • aspect(가로/세로 비율. 16:9 이런거)
  • n(원점에서 near plane 까지의 거리)
  • f(원점에서 far plane 까지의 거리)

에 의해서 이 frustum이 결정됨.

 

frustum에 아예 들어오지 않는 애들은 최종 이미지에 영향을 미치지 않기 때문에, GPU 파이프라인에 들어가기 전에 CPU에서 미리 잘라냄(frustum culling).  그림에서는, view frustum 안에 안 들어오는 원기둥과 구는 안 보이는 거니 잘라냄.

 

그러면 이제 knight만 남음~  

근데 knight도 살짝 걸리는 게 있다. view frustum 바깥으로 살짝 튀어나가는 부분이 있음.

이처럼 frustum에 일부만 들어오고 일부는 잘린다면, 잘린 위치에 vertex를 새로 생성해서 primitive를 만드는 과정(Clipping)이 들어가야 하는데, 이건 rasterization stage에서 해줌.

 

근데!!! 이걸 frustum 형태로 자르기는 쉽지 않음..

따라서 이 frustum을 직육면체 형태(OpenGL에서는 정육면체)로 변환해서 처리해주면 자르기가 훨씬 쉬워질 것임!!

이 변환을 Projection Transform이라고 함. 이로 인해 만들어진 공간(오른쪽 그림)을 clip space라 함.

 


Projection Transfrom

view frustum을 축이 정렬된 2x2x1 사이즈의 큐브로된 공간(clip space)으로 변형하는 변환

 

 

projection transform을 통해 view frustum을 2x2x1 사이즈의 큐브로된 공간(clip space)으로 변형함.

(DirectX : 2x2x1, LHS사용. OpenGL : 2x2x2, RHS사용)

camera space의 object들은 projection transform을 통해 clip space로 오고, 후에 Rasterizer을 통해 clip space에서 clip됨.

 

 

■ 그러면, 이 변환을 어떻게 시키냐?

 

하늘색 선을 projection plane이라고 함.

카메라는 frustum의 knight를 projection plane으로 투영시켜서 보여줄 것이다.

이 과정이 projection transform임. (오른쪽 그림은 투영된 clip space에서의 단면을 자른거)

더보기

※ 현실 카메라는 3차원 => 2차원으로 투영하겠지만,

그래픽스에서는 추후 처리과정을 고려하여 3차원을 그대로 유지하면서 투영의 효과(원근법)를 달성함.

 

여기서 어떤 일이 일어나는지 보자.

왼쪽 view frustum에서 l₁ > l₂이다. 그러나, 오른쪽 clip space로 넘어오면 l₁` = l₂`이 됨! (3D 공간 내에서) 원근법 적용된 것.

(view frustum을 cube 공간으로 변형할 때, 그림처럼 평행하지 않던 projection line들이 모두 z축에 평행하게 변형.)

더보기

딱봐도, rigid 변환이 아님.(knight 보면 scaling.. 느낌의 비선형 변환이 포함되어 있음)

또, 아핀 변환도 아님.(아핀 변환은 평행한 것들을 그대로 평행하게 유지해줌. projection line 보면 엄청 달라짐.)

 

 

 암튼 이런식으로 변환해주는 행렬 M_proj은 다음과 같음!

 

보다시피 우리가 아까 정의했던 4개의 파라미터(fovy, aspect, n, f)를 사용해서 M_proj를 정의할 수 있음~

이를 이용해서 camera space의 object들을 변환해주면 됨.

 

결국에는 near plane0으로, far plane 1로 가져온다~

더보기

※ OpenGL 에서는 near plane은 1로, far plane은 -1로 감. Rasterizer는 LHS로 정의되어 있는 하드웨어 함수라서, RHS를 쓰는 OpenGL은 z-negation(z값 바꾸기)을 해줘서 LHS 기준으로 바꿔줌.

 


◆ RHS vs LHS

OpenGL에서는 오른손 엄지가 z축의 양의 방향을 가리키는 RHS를 사용하고,

DirectX에서는 왼손 엄지가 z축의 양의 방향을 가리키는 LHS를 사용한다. (서로 z축 방향이 반대임)

 

근데 이 차이에 따른 문제가 있음.

그림과 같이 RHS, LHS에서 동일한 좌표의 세모와 네모 object를 찍었음.

그런데 RHS냐, LHS냐에 따라서 카메라로 찍었을 때 이미지가 달라짐!! ㅠㅠ 좌우가 바뀜...

 

 

솔루션은 간단하다.

각 정점들의 z 좌표만 바꿔주면 됨. 카메라의 EYE, AT, UP의 z 좌표도 같이 바꿔줌.

그림처럼 LHS에서 z 좌표를 다 바꿔줬더니, 이번에는 똑같은 이미지가 나옴!

 

이 개념을 기초로 Projection Transform이 수행된다.

z축 방향 바뀐 걸 볼 수 있음. 따라서 OpenGL과 DirectX에서의 M_proj도 다르게 나온다는 점~

 

더보기

■ OpenGL version

 

'게임 > 그래픽 프로그래밍' 카테고리의 다른 글

7. Image Texturing  (0) 2023.05.26
6. Rasterization  (0) 2023.05.13
4. Input Assembler & Vertex Processing(1)  (4) 2023.05.12
3. Spaces and Transforms  (0) 2023.04.25
2. Vectors and Matrices  (0) 2023.03.31
Comments