GPU에서 rendering은 아래와 같은 pipeline 구조로 이루어집니다.

이는 programmable stages(파란색 블록) 와 hard-wired stages(노란색 블록)로 나누어집니다.
shader는 사용자가 정의해야하는 program이며, vertex shader 와 fragment shader로 이루어져 있습니다.
반면, rasterizer 와 output merger는 하드웨어에서 수행되며 사용자가 조정할 수 없는 함수입니다.
vertex shader에서 world transform, camera transform 등 여러 변환이 이루어집니다. rasterizer는 triangle mesh를 fragments로 나누는 과정을 수행합니다. fragment shader는 각 fragment color를 계산하여 입히는 과정을 거칩니다. 최종적으로 output merger에서 fragment color를 사용하여 pixel color를 결정합니다.
vertex shader에서 이루어지는 가장 중요한 과정은 바로 변환입니다. 컴퓨터 그래픽스에서 정점에 관해서 연산을 취하는 것 모두 변환이라고 말합니다. 구체적으로 world transform, view transform, projection transform 등이 있습니다. 일련의 과정을 플로우 차트로 나타내면 아래의 그림과 같습니다.


world transform은 4장에서 배웠듯이 scaling, roation, translation 과정을 통해 object space에서 world space로 변환하면 됩니다. 이러한 변환은 vertex positions에 적용한 것입니다. 한 가지 고려하지 않은 점은 바로 vertex normals 에 대한 변환입니다. traiangle normals를 고려해보면 vertex position에 적용한 변환 이 non-uniform scaling 이라면 이러한 변환을 normal에 적용한다면 normal은 그 성질을 잃어버리게 됩니다. 여기서 non-uniform scaling은 각 축에 대해서 비율이 깨지는 경우를 뜻합니다. 아래의 그림을 통해 확인할 수 있습니다.

normal이 여전히 orthogonal하려면 normal 벡터에 를 취하면 됩니다.(증명은 생략합니다) 이렇게 uniform scaling일 때는 L 또는 을 취해주면 되지만, non-uniform scaling일 때는 를 취해줘야한다는 불편함이 있습니다. 따라서 그냥 모든 경우에 를 취하기로 합니다. 이렇게 world transform에서 vertex positions 와 vertex normals 에 대한 변환을 모두 살펴 보았습니다. 이제 world space로 변환하였으니 camera space로 변환해주어야합니다. 이유는 어떠한 피사체를 카메라가 촬영하였을때, 카메라가 바라보는 camera space와 실제 물체가 존재하는 world space의 공간은 다른 좌표를 가지고 있기 때문에 이를 일치시켜 주어야 합니다.
camera space에서는 camera pose (position + orientation)를 정의합니다. 카메라의 position은 camera space 축을 기준으로 이루어지는 좌표이고 orientation은 카메라의 위치를 정의하여 고정하는 것을 의미합니다.

따라서 camera space는 {u,v,n, EYE}로 나타내며 은 orthonormal basis 입니다. 여기서 u,v,n을 구하는 방법은 위의 그림처럼 구할 수 있습니다.
이제 camera space에 대한 이해를 바탕으로 veiw transform에 대해서 살펴보겠습니다. view transform은 world space에서 camera space로 변환하는 과정을 뜻합니다.

world-space의 objects는 camera space로 새롭게 정의될 수 있습니다. 일반적으로 space change라고 부릅니다. wolrd space O 에서 EYE 로 space change가 이루어집니다.
먼저 를 world space의 원점(origin)으로 translate을 수행합니다. 이렇게 하면 world space와 camera space의 원점이 일치하게 됩니다.

translation을 수행하면 world space와 camera space는 origin을 서로 공유하기 때문에 space-change task를 에서 로 basis change 하는 것과 같게 됩니다.
4장에서 배웠듯 basis change는 rotation으로 수행됨을 알고 있습니다.

rotation matrix를 알고 있다면 를 곱해주게 되면 다시 원래의 basis로 되돌릴 수 있음을 알고 있습니다. 따라서 camera space를 이룰때 구했던 축에 대해서 transpose matrix를 곱해주면 됩니다. 정리하면 space change = translation + basis cange 입니다. 는 world space에 있는 모든 objects를 camera space로 변환하도록 적용됩니다.



보기 쉽게 비디오로 확인해보겠습니다.

는 물체의 모양을 변화시키지 않는 rigid motion입니다.

world-space point, p는 camera space에서 로 정의됩니다. world space basis를 rotation 한 후 translation하여 camera space에 있는 점으로 표현하게 됩니다. 아래의 그림을 살펴보겠습니다.

오른손 법칙, 왼손 법칙입니다. 엄지 손가락을 기준으로 나머지 손가락이 감기는 방향으로 좌표가 설정되는 시스템을 의미합니다. 따라서 오른손 법칙은 자연스럽게 반시계 방향으로 축이 설정되고 왼손 법칙은 시계 방향으로 축이 설정됩니다. 여기서 반시계는 counter clock-wise, 줄여서 CCW라고 하고 시계 방향은 clock-wise로 줄여서 CW라고 부릅니다.

그래픽스에서 오른손 법칙과 왼손 법칙이 아주 중요합니다. 그 이유은 바로 shader는 RHS, rasterizer LHS를 따르도록 설계되어있고 이는 카메라의 위치가 바뀌면 피사체의 위치도 바뀌기 때문입니다. 그림을 확인해보겠습니다.
양의 방향 z축에 카메라가 놓여있다고 한다면 RHS에서는 삼각형, 사각형 순으로 놓이게 됩니다. 하지만, LHS에서는 반대로 사각형, 삼각형 순으로 피사체가 찍히게 됩니다. (만약 사용자가 보는 화면은 RHS이고 게임 시스템은 LHS라면 자칫 아군을 죽이는 게임이 될 수도 있습니다..)

이러한 문제를 해결할 수 있는 가장 간단한 방법은 LHS에서 z축에 (-1) 을 곱해주는 것입니다.

View Frustum 이라는 새로운 개념이 등장합니다. 지금까지 object space -> world space -> camera space를 하였으니 이제 마지막으로 clip space로 변환해주어야합니다. clip space는 내가 보고자 하는 영역만 골라서 보기 위해 필요한 공간입니다. clip space로 가져오기 위해서는 projection transform을 거쳐야하는데 이전에 이해해야할 것이 바로 view frustum입니다.(아자아자!! 할 수 있다!!)
카메라 공간의 축을 라고 하자. 은 카메라의 external parameters 이다. 이제 interneals parameters를 정의해보자. 바로 lens를 zoom-in and -out 하며 조절하고자 한다. infinite pyramid를 fovy 와 aspect로 정의하자. (fovy는 field of view along y-axis, .카메라가 수직 방향(y축)에서 볼 수 있는 시야각(각도)이라고 이해하면된다)
fovy는 projection시 아주 중요한 요소인데 fovy가 커지면 더 넓은 시야를 갖게 되지만 각 객체는 더 작게 보입니다. 실제로는 aspect(종횡비)를 더 많이 사용합니다. 아래의 그림처럼 fovy, aspect를 통해 카메라의 시야각을 설정할 수 있습니다.

그 후, 를 정의하며 각각 near, far planes 까지의 거리를 뜻합니다. 이를 정의하고 나면 truncated pyramid가 만들어지고 이를 view frustum이라고 합니다. 이제 내가 보고자하는 주전자만 시야에 있게 되고 나머지 원기둥, 구는 보이지 않게 됩니다.

하지만, 주전자에서도 잘린 부분이 있는 것을 확인할 수 있습니다. 이러한 부분은 어떻게 처리할까요? GPU 상에서 view frustum 경계 밖에 있는 polyhon을 clip합니다. 오직 view frustum 내부의 polygon만 보여지게 됩니다.

쉬어가는 타임으로 view frustum이 어떻게 사용되는지 예시를 보겠습니다.

게임을 할 때 1인칭 모드, 조종자 모드 등에서 view frustum이 사용됩니다.
Pyramidal view frustum은 clipping을 하기 위한 것이 아니라 원점을 중심으로 한 axis-alined 2x2x2-sized cube로 deform하기 위해 사용됩니다. 이 과정을 projection transform 이라 부릅니다. camera-space objects는 projection-transform된 후 cube에 따라 clipped 됩니다.

projection-transformed objects를 clip space 라고 부릅니다. 그러다면 이런 과정이 왜 projection인지 궁금할 수 있습니다. 뭔가 투영되었다던지, 2D 평면에 놓이지 않았는데 말이죠. 이는 view frustum에서 axis-alined cube로 변환하는 과정에서 원근법이 제거되기 때문에 projection transform이라고 합니다.
대표적인 예로 pin-hole camera model을 들 수 있습니다. pin-hole 카메라는 3D object를 2D projection plane 또는 image plane에 projection하는 것입니다. 컴퓨터 그래픽스에서는 카메라를 center of projection(COP)로 줄입니다. 따라서, 우리는 동일한 focal length를 사용하는 virtual image plane을 생각할 수 있습니다. 아래의 그림을 통해 확인해보겠습니다.

COP를 통해 image plane에 2D image의 상이 맺히는 것을 알 수 있습니다. image plane과 focal length만큼을 COP 앞에 image plane이 있다고 생각한다면 동일한 크기의 상을 얻을 수 있을 것입니다. 이를 응용하여 view frustum을 바라보겠습니다.
view frustum은 projection lines로 수렴하는 선들로 그려질 수 있습니다. 그리고 이러한 선들은 가상의 카메라 EYE가 놓인 부분 COP에 수렴합니다. 투영선상의 모든 3차원 점들은 투영된 이미지에서 하나의 2차원 점으로 매핑됩니다. 이는 perspective projection (원근 투영)의 효과를 가져오는데, 멀리 있는 객체가 더 작게 보이게 만듭니다.

perspective projection은 투영선이 z축에 평행하도록 합니다. 카메라가 무한히 멀리 위치한 상태에서도 보편적인 투영선을 따라서 관찰이 이루어지며 투영 변환은 3차원 공간 내에서의 원근 투영 효과를 가져옵니다. 아래의 비디오를 통해 확인해보겠습니다.

이러한 변환은 어떤 연산을 통해 이루어질 수 있을까요?
Projection transformation matrix라고 하며 증명은 생략하겠습니다.

정리해보면 vertex processing에서 아래의 flow chart 순으로 변환이 이루어집니다.

앞에서 설명했듯 shader와 달리 rasterizer는 하드웨어로 구현되어있습니다. 그리고 rasterizer는 clip space를 left-handed이길 기대합니다. rasterizer는 사용자가 수정할 수 없기 때문에 shader에서 RHS -> LHS로 변환해서 출력해주어야 합니다. z축에 대해서 (-1)을 곱해주면 되기 때문에 projection transform matrix는 다음과 같아집니다.

이를 한번에 정리하면 아래의 그림과 같이 나타낼 수 있습니다.

이러한 연산은 4D homogeneous coordinates에서 이루어집니다. 변환이후 Cartesian coordinates ( 로 나누는 과정)으로 변환한 값이 cube로 얻어집니다. 이를 일반화하면 아래의 수식과 같습니다.

이렇게 vertex processing의 과정에 대해서 모두 살펴보았습니다. 다음은 OpenGL ES 에서 shader가 어떻게 구현되는지 살펴보겠습니다.
참고자료
고려대학교 정보대학 한정현 교수님 수업