정점 처리 (vertex processing)
로컬 공간의 정점들에 월드 변환, 뷰 변환, 클립 변환 및 조명 등을 연산하여 적용하는 단계.
월드 변환
선형 변환인 회전, 크기 변환과 아핀 변환인 이동 변환을 적용한다.
이동 변환은 한 차원 높은 행렬을 사용해야 하기 때문에 3차원 공간 기준으로는 4x4 행렬을 사용한다.
참고로 왼손 좌표계(DX)는 회전각이 양수라면 시계, 오른손 좌표계(OpenGL)는 반시계 방향으로 회전한다.
또한 DX는 행벡터를 사용하기 때문에 벡터*행렬 순서로 곱하는 것과 더불어 SRT 순서로 곱한다.
Vworld = Vlocal * S * R * T
V = 정점, S = 크기 변환 행렬, R = 회전 변환 행렬, T = 이동 변환 행렬
정점에 계산되는 월드 행렬(모델링 행렬)을 M이라고 할 때, 크기 변환 행렬의 x,y,z가 균등한 비율의 축소 및 확대라면 노말 벡터에도 적용이 가능하다.
하지만 비균등 축소 및 확대를 포함한다면 사용이 불가능하다. 비균등 축소 및 확대가 적용된 모델링 행렬을 노멀 벡터에 적용한다면 수직 관계가 깨지게 된다.
그래서 노말 벡터에는 M의 역행렬의 전치 행렬을 곱해서 수직 관계를 유지시켜준다.
* 노말 벡터 변환과 관련된 자세한 내용은 34p 참고
뷰 변환
◾ 카메라 공간
정점들이 월드 공간에 배치되면 원하는 부분만 관찰하기 위해 카메라의 파라미터를 설정해야 한다.
월드 공간의 모든 물체는 카메라 공간으로 변환되고, 클리핑을 통해 효율적인 렌더링 알고리즘 설계가 가능해진다.
뷰 변환을 위한 뷰 행렬을 구하는 대표적인 방법으로 EYE, AT, UP 세 가지 파라미터를 사용하여 구하는 방법이 있다.
EYE : 카메라의 좌표
AT : 카메라가 바라보는 기준점 (또는 물체)
UP : 월드 y축 기저벡터
카메라의 forward(z축) 벡터는 AT - EYE를 정규화 시키면 구할 수 있고, right(x축) 벡터는 forward와 UP을 외적하여 구할 수 있다. 마지막으로 forward와 right를 외적하면 up(y축)벡터까지 모두 구할 수 있다.
◾ 공간 이전과 뷰 행렬
월드 공간의 기저벡터는 각 축에 해당하는 e1(1,0,0), e2(0,1,0), e3(0,0,1)이다. 이는 {O, e1, e2, e3}으로 표현할 수 있다.
카메라 공간의 원점은 카메라의 위치에 해당되고 각 축 역시 카메라의 기저벡터에 해당되기 때문에 {EYE, right, up, forward}로 표현할 수 있다.
월드 공간의 좌표를 카메라 공간의 좌표로 변환하는 것을 뷰 변환 또는 카메라 변환이라고 한다.
간단하게 생각하면 된다. 카메라 공간에서는 원점을 카메라의 좌표로 봐야한다. 그러면 카메라를 원점으로 옮기는 행렬을 만들고 그 행렬을 정점들에 곱해주면 카메라 공간에 배치된것처럼 보이게 될 것이다.
계산 또한 매우 간단하다. 어떤 로컬 공간의 정점에 모델링 행렬 M을 곱해서 월드 공간에 배치했다면 M의 역행렬을 곱하면 다시 로컬 공간(0, 0, 0)으로 돌아올 것이다. 마찬가지로 카메라에 M의 역행렬을 곱하면 (0,0,0) 즉, 원점으로 돌아오게 된다. 카메라는 스케일링이 의미가 없기때문에 이동 행렬의 역행렬 * 회전 행렬의 역행렬(T-1 * R-1 = V)을 곱해주면 된다. (행벡터 기준)
이제 각 정점에 V를 곱해주면 정점들은 카메라 공간으로 이동하게 된다.
정점별 조명
차후 조명 연산에서 카메라와 정점간의 각도에 따라 반사된 빛이 카메라에 얼마나 들어오는지 결정하게 된다.
투영 변환
뷰 변환에 의해 모든 정점들이 카메라 공간 {EYE, right, up, forward}로 변환되었다.
이제 이 정점들을 제한된 카메라 시야에 렌더링 해볼 차례이다.
◾ 뷰 프러스텀 (절두체)
일반적으로 카메라의 시야는 제한되어 있어서 카메라 공간의 모든 물체를 화면에 담아낼 수 없다. 이 가시 영역을 뷰 볼륨이라고 부르는데, fovy, aspect, n, f 총 4가지 파라미터를 사용하여 결정한다.
fovy : field of view. 시야각
aspect : 뷰 볼륨의 종횡비 (ex: 4:3, 16:9)
n : near plane. 근평면
f : far plane. 원평면
위의 파라미터를 통해 생성된 절두체 외부에 놓인 물체는 뷰 프러스텀 컬링을 통해 렌더링 파이프라인에 들어가지 못하게 해서 보이지 않는 것으로 처리한다.
그런데 물체가 절두체의 경계에 존재하는 경우가 발생하는데, 이 때 해당 물체 전체가 렌더링되지 않는것이 아니라 절두체 외부에 있는 정점들만 잘라내고 경우에 따라 새로운 삼각형을 생성하는 클리핑 과정이 필요하다.
클리핑을 하기 전에 개별적인 폴리곤 메쉬를 감싸는 바운딩 볼륨을 미리 계산해두고 바운딩 볼륨이 절두체 외부에 있는지를 우선적으로 검사한다.
바운딩 볼륨은 추가적인 비용이 발생하는 것이지만 약간의 CPU 비용을 지불하는 대신 상당량의 GPU 비용을 절감하는 효과를 얻을 수 있다.
폴리곤 메쉬가 절두체의 평면과 겹치는 경우, 절두체 안쪽에 놓인 부분만 잘라내서 파이프라인의 다음 단계로 보낸다.
◾ 투영 행렬
절두체는 피라미드 모양이기 때문에 비스듬한 면이 존재해서 클리핑 연산이 복잡해지는 문제가 있다.
이를 위해 직육면체(2x2x1 크기)의 새로운 뷰 볼륨으로 변환하여 클립 공간으로 보내는 투영 변환이 필요해진다.
이름과는 달리 투영 변환은 카메라 공간의 3차원 물체를 2차원으로 투영하는 대신에 또 다른 3차원 물체로 변형시키는 변환이다.
절두체는 원점에 위치한 카메라로 수렴하는 투영선의 집합으로 이해할수도 있다.
이 투영선들을 직교 투영하여 모두 평행하게 만들어서 원근감을 실현 시킨다. 이것이 투영 변환이다.
투영 변환의 중요한 특징 중 하나는 아핀 변환에서는 마지막 요소인 w가 1이었지만 투영 행렬은 그렇지 않다.
투영 행렬의 유도는 글로 작성하기가 어려워서 책을 다시 보는 것이 좋을 것 같다. (p.51, 이득우의 게임수학 p.402)
'이론 > 그래픽스' 카테고리의 다른 글
[Chapter 5] 조명 및 쉐이더 (0) | 2023.05.17 |
---|---|
[Chapter 4] 프래그먼트 처리와 출력 병합 (0) | 2023.05.11 |
[Chapter 3] 래스터라이저 (0) | 2023.05.11 |
[Chapter 1] 폴리곤 메쉬 (0) | 2022.09.16 |