- 이 그림에서 파란색으로 보이는 쉐이더 부분은 프로그램과 동의어이다.
- 즉, 우리는 GPU 렌더링을 위해서 정점 쉐이더(vertex shader)와 프래그먼트 쉐이더(fragment shader)라는 두 가지 프로그램을 작성해야 한다.
- 반면, 래스터라이저(rasterizer)와 출력 병합기(output merger)는 하드웨어로 고정된 단계로, 정해진 연산과 기능만을 수행한다.
- 정점 쉐이더는 정점 배열에 저장된 모든 정점에 대해서 변환(transform)을 비롯한 다양한 연산을 수행한다.
- 래스터라이저는 변환된 정점들로 삼각형들을 조립한 후, 각 삼각형 내부를 차지하는 프래그먼트(fragment)를 생성한다.
- 프래그먼트는 컬러 버퍼의 한 픽셀을 갱신하는 데 필요한 데이터를 총칭하는 것이다.
- 래스터라이저가 출력한 프래그먼트는 하나하나 프래그먼트 쉐이더로 입력되어, 라이팅과 텍스처링 등의 작업을 거쳐 색상이 결정된다.
- 출력 병합기는 이러한 프래그먼트와 현재 컬러 버퍼에 저장된 픽셀 중 하나를 선택하거나 혹은 이들의 색을 결합하여 컬러 버퍼를 갱신한다.
- 월드 변환의 절반은 4장에서 설명했으며, 이번 5장에서는 절반과 나머지 두개를 설명한다.
5.1 노멀의 월드 변환
- 월드 변환은 아핀 변환들로만 구성되었다면 [L | t]로 표기할 수 있다.
- L은 '누적된 선형 변환'을, t는 '누적된 이동'을 표현하는데, 노멀 변환에 있어 t는 무시해도 된다. 벡터는 이동에 의해 영향 받지 않기 때문에 생각을 안해도 된다.
- 위 그림에서 L을 노멀에 적용했을 때 문제가 발생했던 것은 L이 비균등 축소확대였기 때문이다.
→ 만약 L이 비균등 축소확대를 포함하지 않는다면, 즉 L이 회전, 이동, 균등 축소 확대 중 하나이거나 이들이 결합된 경우라면, 노멀에 L을 적용해도 된다. - 하지만, 알고리즘을 단순화하기 위해, L이 비균등 축소확대를 포함하건 말건 노멀 변환에는 무조건 L^-T를 사용할 것이다.
→ 굳이 조건을 하나 더 달아 노멀에 L을 적용하지 말고 모든 경우에 L^-T를 사용하는 게 좋기 때문이다. - 이해를 돕기 위하여 위 그림에서는 삼각형 노멀을 사용했지만, 폴리곤 메시 렌더링에 실제로 사용되는 것은 정점 노멀이다. 월드 공간 정점 노멀 계산에도 L^-T가 그대로 쓰인다.
5.2 뷰 변환
- 월드 변환이 완료되어 모든 물체가 월드 공간에 모아졌다고 가정하자. 월드 공간의 특정 영역을 스크린에 렌더링하기 위해서는 가상 카메라의 위치와 방향을 설정해야 한다.
5.2.1 카메라 공간
- EYE는 월드 공간에서의 카메라 위치이다.
- AT은 월드 공간에서 카메라가 바라보는 기준점이다.
- UP은 카메라의 상단이 가리키는 방향을 대략적으로 묘사하는 벡터이다.
→ 이들 파라미터를 이용해 카메라 공간(camera space)이 정의되는 데, 그 원점은 EYE에 놓여진다.
- 카메라 공간으 ㅣ기저를 {u, v, n}으로 표기하자. 가운데 상자는 EYE, AT, UP을 사용해 어떻게 {u, v, n}이 계산되는지 보여준다.
- 우리는 카메라 공간을 {u, v, n, EYE}로 표기한다.
5.2.2 공간 이전과 뷰 행렬
- 하나의 공간에서 정의된 물체를 다른 공간으로 옮기는 것을 일반적으로 공간 이전(space change)이라고 부르는데, 월드 공간에서 카메라 공간으로의 이전은 카메라 좌표계 {u, v, n, EYE}를 월드 좌표계 {e1, e2, e3, O}에 포개 놓는 과정으로 묘사될 수 있다.
- 이를 위해서는 EYE를 먼저 O로 '이동'시킨 뒤 {u, v, n}을 {e1, e2, e3}와 일치하도록 '회전'시키면 된다.
- 이 과정에서 모든 물체는 카메라 좌표계를 따라 같이 움직인다.
- 월드 공간 좌표가 (10, 2, 0)이던 주둥이 끝 정점도 이동과 회전을 거쳐 (0, 0, -10)의 좌표를 가지게 되었는데, 이제 월드 공간과 카메라 공간이 동일해졌으므로, 이 월드 공간의 좌표 (0, 0, -10)을 그대로 카메라 공간 좌표로 취하면 된다.
- 월드 공간에서 카메라 공간으로의 이전을 뷰 변환(view transform)혹은 카메라 변환(camera transform)이라 부른다.
- 이동에 의하여 월드 공간과 카메라 공간은 원점을 공유하게 된다.
- 따라서, 기저{u, v, n}은 회전을 통하여 {e1, e2, e3}에 포개질 수 있다.
- 이 회전은 카메라 공간의 기저 {u, v, n}을 행으로 가지는 행렬로 정의된다.
- 결국 물체들은 R에 의해 회전되어 공간 이전이 완료된다.
- 공간 이전을 구성하는 이러한 회전은 기저 이전(basis change)이라고 부른다.
공간 이전은 앞으로 여러번 언급되고 중요한 내용이니 완벽하게 이해해야한다.
5.3 오른손 좌표계와 왼손 좌표계
- 3차원 카테시안 좌표계는 오른손 좌표계와 왼손 좌표계로 나뉜다.
- Direct3D는 왼손 좌표계를 사용하지만, OpenGL과 OpenGL ES는 오른손 좌표계를 사용한다.
→ 따라서, 이 책도 기본적으로 오른손 좌표계를 사용한다.
- 예를 들어, OpenGL에서 모델링한 물체를 Direct3D로 포팅하는 경우가 이에 해당한다.
- (a), (b)처럼 좌우가 뒤바뀌어졌음을 알 수 있다.
해결 방법은 간단하다. 포팅 시 물체와 카메라 파라미터의 z좌표의 부호를 바꾸면 된다.
- z좌표의 부호를 바꾸는 것은, (a)에서 (c)로 넘어오는 과정이 직관적으로 보여주는 것처럼, z축을 반대 방향으로 돌리는 것으로 생각하면 이해가 쉬울 것이다.
5.4 투영 변환
- 월드 공간에서 정의된 EYE, AT, UP을 카메라의 '외부'파라미터라고 본다면, 이제 카메라의 렌즈를 선택하고 줌인/줌아웃을 조절하는 것에 해당하는 '내부'파라미터를 정의할 차례이다.
5.4.1 뷰 프러스텀
- 일반적으로 카메라의 시야(Field of view; fov)는 제한되어 있기 때문에 카메라 공간의 모든 물체를 스크린에 담아낼 수 없다.
- 카메라의 가시 영역을 뷰 볼륨(veiw voilume)이라 부르는데, 이는 fovy, aspect, n, f 네 가지 파라미터를 사용해 결정된다.
fovy : field of view y-axis (y축 기준의 시야각)
aspect : 뷰 볼륨의 종횡비(가로세로 비율 = width/height)
- fovy와 aspect에 의해 정의된 뷰 볼륨은 꼭지점을 원점에 두고 -z축을 중심축으로 가진 무한한 크기의 피라미드가 된다.
- 뷰 볼륨을 정의하는 나머지 파라미터 n과 f는 각각 원점으로부터 전방 평면(near plane)과 후방 평면(far plane)까지의 거리를 나타낸다.
fovy와 aspect에 의해 정의된 무한한 크기의 뷰 볼륨은 z축에 수직인 전방 평면 z = -n과 후방 평면 z= -f에 의해 절단되어 유한한 크기의 뷰 볼륨으로 바뀐다.
- 이를 뷰 프러스텀(view frustum) 혹은 절두체라고 부른다.
- 원통 및 구와 같이 뷰 프러스텀 바깥에 놓인 물체는 대개 미리 걸러져서 GPU 파이프라인에 들어가지 못하게 한다. (=culling)
5.4.2 투영 행렬
- 투영 변환(projection transform)은 한 마디로 말하자면, 피라미드 모양의 뷰 프러스텀을 좌표계의 주축에 나란한 2x2x2 크기의 정육면체 뷰 볼륨으로 변형하는 것이다.
- 카메라 공간 물체는 이렇게 투영 변환을 거친 뒤, 2x2x2 크기의 정육면체에 대해 클리핑된다.
- 이런 점에서, 투영 변환 이후에 물체가 놓이는 공간을 클립 공간(clip space)이라고 따로 부른다.
- 뷰 프러스텀은 원점에 위치한 카메라로 수렴하는 투영선(projection lines)들의 집합으로 이해할 수 있다.
- 3차원 공간에서는 l1이 l2보다 길지만 투영 평면에서 이들은 동일한 길이를 가지게 된다. 즉 멀리 있는 물체가 작게 보이게 되는데 이것이 바로 원근법이다.
- 투영 변환의 결과, 모든 투영선들은 서로 평행해져 z축에 나란해졌다. 즉, 단일한 투영 방향을 가지게 되었다.
- 투영 변환은 정점 쉐이어가 수행하는 마지막 연산이다. 투영 변환된 물체는 이제 하드웨어로 고정된 래스터라이저로 들어갈 것이다.
- 뷰 프러스텀을 2x2x2 크기의 정육면체로 변형하는 투영 행렬은 다음과 같다.
- 클립 공간의 물체는 래스터라이저로 입력된다. 클립 공간은 '오른손'좌표계이다.
- 그런데 래스터라이저는 모든 물체가 '왼손' 클립 공간에서 정의되어 있다는 가정에서 설계되어있다.
- 따라서 우리는 래스터라이저로 진입하기 위하여 오른손 좌표계를 왼손 좌표계로 변환해야 한다.
→ 이를 위해서는 정점 z좌표의 부호를 변경하면 된다. - 따라서 v'의 z좌표 부호를 바꾸기 위해서는 세 번째 행의 모든 원소의 부호를 바꾸면 된다.
출처
[OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문]을 보고 공부하고 정리한 내용입니다.
'공부 > Open GL ES를 이용한 3차원 컴퓨터 그래픽스 입문' 카테고리의 다른 글
[OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문] 챕터 7 - 래스터라이저 (0) | 2022.02.15 |
---|---|
[OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문] 챕터 6 - OpenGL ES와 쉐이더 (0) | 2022.02.14 |
[OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문] 챕터 4 - 좌표계와 변환 (0) | 2022.02.12 |
[OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문] 챕터 3 - 모델링 (0) | 2022.02.11 |
[OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문] 챕터 2 - 수학 기초 (0) | 2022.02.11 |