지금까지 정점들로 이루어진 object가 어떻게 변환하는지 알아보았다.
GPU에서 어떻게 렌더링이 되는지 보자. 삼각형이 스크린 안에서 여러 개의 픽셀들을 차지하고, 그 픽셀의 색상을 정하는 정보를 rasterizer가 모아서, 픽셀 위치마다 저장해 놓는다. 이를 fragment라고 한다. 그냥 예비 픽셀, 후보 픽셀이라고 이해하면 된다. fragment shader는 실제로 fragment color를 결정한다. 그리고 마지막으로 output merger가 어떻게 보여줄 건지를 결정해서 최종 스크린을 보여준다.
이번 장에서는 vertex shader가 하는 일을 하나하나 살펴볼 것이다.
이제 이러한 물체가 어떻게 화면에 표현되는지 알아보도록 하자. vertex shader는 object space에서 정의된 정점을 최종적으로 clip space로 옮겨주는 역할을 해야 한다. 아래와 같은 단계를 거쳐 옮겨준다.
World Transform (Object space -> World space)
저번 포스팅에서 world transform에서 변환을 행렬곱으로 표현하는 것을 배웠다.
vertex array의 중요한 정보 중 하나인 vertex normal은 어떻게 변환시켜야 할까?
앞에서 SDT의 변환은 Affine transform으로 변환을 했고, 이러한 변환을 [L|t] 라고 표현했다.
x축으로 반 줄이고, y축으로는 그대로 놔두는 변환이 있다고 하자. normalize 까지 해보면 위와 같은 결과를 얻을 수 있다.
이러한 normal은 눈으로 봐도 삼각형에 직각이 아니다. 그럼 normal의 정의 자체를 깨뜨려버리게 된다.
그러면 어떻게 해야 할까?
결론적으로는 L의 inverse transpose를 이용하면 된다. (L^(-T))
L의 inverse transpose를 적용하면 위의 그림처럼 삼각형의 직각인 normal로 transpose 된다.
L의 inverse transpose를 이용하는 이유는 다음과 같다. 먼저 삼각형을 이루는 세 vertex를 각각 (p, q, r) 이라고 하자.
이때, 이 삼각형의 normal이 n이라면(수직이므로) nT dot (q-p) = 0 이다.
그리고 L에 의해 변환된 vertex를 (p' q' r')라고 하고 normal을 n'라고 하자.
즉, Lp=p' , Lq=q' 이다. 이때 L의 inverse를 각 항에 곱하면 p = L^(-1)p' , q = L^(-1)q'가 된다.
이를 이전 식에 대입하면 nT dot (L^(-1)p'- L^(-1)q') = 0이다.
이를 고쳐쓰면 (p'-q')T x L^(-T) x n = 0이 된다.
n'이 L^(-T)n와 같으므로 n을 n'로 만드는 행렬은 L^(-T)가 된다.
비균등확대가 아닌 경우에는 L을 그대로 사용해도 무관하나 연산의 일관성을 위해 모든 연산에 대해 L 의 inverse transpose를 이용해 연산한다.
View Transform (World space -> Camera space)
이제부터 world transform 이후 과정을 보자.
world 공간에 object들을 놓았는데 이제 카메라가 이를 본다고 생각하자. 사람/카메라 등 보는 방향에 따라 물체가 스크린에 다르게 표현되기 때문에 카메라(눈)가 보는 공간을 Camera space라고 한다. 그리고 World space에서 Camera space로의 변환을 View transform이라고 한다.
카메라의 위치를 EYE라 하고, 카메라가 보는 물체의 점을 AT, 카메라의 위쪽이 가르키는 방향을 UP이라고 한다. 카메라가 기울려서 촬영할 수 있기 때문에 UP이 필요하다.
이때 카메라 공간의 basis는 {u, v, n}으로 표현되는데 아래 식과 같다.
- n : 먼저 EYE와 AT을 잇는 직선이 필요하다. 그리고 이것을 unit vector로 만들어준다.
- u : UP과 n을 cross product 한다. 오른손 법칙 적용하면 u의 방향이 나온다. 그리고 unit vector로 만들어준다.
- v : n과 u를 cross product 한다. normalize 하지 않는 이유는 이미 n과 u가 unit vector 이기 때문이다.
이렇게 u, v, n은 서로 수직이므로 orthonormal한 관계를 가진다.
심지어 EYE가 원점의 역할을 하므로 완벽한 3차원 좌표계를 정의한다.
그리고 이 좌표계를 Camera space라고 정의한다.
따라서 World space를 Camera space로 옮길 때, 이전에 진행했던 것과 같은 방식으로 {x, y, z}를 {u, v, n}으로 맞춰주면 된다.
AT의 좌표는 Camera space로 봤을 때 (0, 0, -10)이 된다.
이렇게 World space의 좌표를 Camera space의 좌표로 바꾸면 Rendering이 쉬워진다!
View Transform 예시
Camera space {u, v, n, EYE}와 World space {e1, e2, e3, O} 가 있다.
우리는 World space 좌표를 Camera space 좌표로 바꾸고 싶다.
그렇게 하기 위해서는 Camera space 좌표를 World space 좌표에 포개지도록 하면 된다!
가장 먼저 해야할 일은 둘의 원점이 다르기 때문에 EYE를 원점으로 translation (-18, -8, 0) 해야 한다. 그럼 원점이 일치가 된다.
그리고 나서 rotation 시키면 (e1, e2, e3)와 일치되게 (u, v, n)을 회전시키면 된다.
이렇게 변환하면 object를 World space에서 Camera space로 옮길 수 있다.
View Frustum
이제 모든 물체가 카메라 공간에 들어왔다고 하자.
카메라 공간은 {u, v, n}을 이제 다시 {x, y, z}라고 표현하자. (u,v,n 인건 그대로이나 World space는 이제부터 고려 대상이 아니므로 혼란의 여지가 없어 x, y, z로 표현한다.)
우리의 시야는 모든 물체를 담지 못한다. 따라서 시야가 담을 수 있는 영역을 지정하고 이 범위 내의 물체만 screen에 표현하도록 해야한다. 카메라나 사람 눈에는 시야 각이 존재하기 때문에 모든 물체를 표현하고자 한다면 어안렌즈를 사용한 것과 같은 왜곡이 생긴다.
위, 아래, 좌우방향으로 시야각을 결정한다. 시야 안으로 들어와 표현되는 영역을 View frustum이라고 한다. 이때 너무 가까운 물체, 너무 먼 물체는 표현되지 않고 시야각 바깥의 물체도 포함되지 않는다. 위 그림에서는 주전자만 렌더링이 된다. 이렇게 시야각 바깥의 물체를 버리는 것을 view-frustum culling이라고 한다.
만약 물체 중 일부만 이 view frustum에 표현된다면 바깥 부분은 잘라져 버리게 된다. 위 그림에서 주전자의 손잡이가 잘린다. 이렇게 자르고 버리는것을 clipping이라고 한다. 그런데 이 부분만 자르는 게 쉽지가 않다. 어떻게 해야 할까?
Projection Transform (Camera space -> Clip space)
View frustum을 정육면체로 표현해보자. 이를 Projection transform이라고 한다.
Projection transform은 View frustum의 사각뿔대를 2x2x2의 정육면체로 변환시키는 행렬이다.
Projection transform을 적용하면 Camera space에서 Clip space로 전환된다.
모든 물체들이 투영(project)가 돼서 필름에 맺히게 되고, 우리는 이 필름을 projection plane이라고 한다. projection plane을 이용해 원근법을 표현하게 된다. 즉, 멀리있는 물체는 작아보이고 가까운 물체는 커진다.
그러나 l1, l2는 Projection transform을 거치면 길이가 같아진다
.
이 과정이 끝나면 vertex shader가 하는 역할은 끝난다.
이제 우리는 Object space에서 World space, 그리고 Camera space에서 Clip space까지 물체를 이동시켰다.
이를 통해 모델링을 한 물체가 어떻게 눈(카메라)에서 보이는지 알게 되었다.
Ref.
Introduction to Computer Graphics with OpenGL ES (J. Han)
'☘️ Computer Graphics > Fundamental' 카테고리의 다른 글
CG - Image Texturing (0) | 2022.07.18 |
---|---|
CG - Rasterizer (0) | 2022.07.16 |
CG - Spaces and Transforms (0) | 2022.07.14 |
CG - Modeling (0) | 2022.07.12 |
CG - Rendering pipeline 개요 (0) | 2022.07.12 |