Daily Life of BlueRose

컴퓨터 & 코딩 공부/컴퓨터 그래픽스 & 언리얼 엔진

컴퓨터 그래픽스 - (버텍스 셰이더/래스터라이저) 좌표계 변환

푸른로즈 2024. 10. 15. 21:57
728x90

여는글

어떤 물체를 우리가 바라보고 인식하기까지 여러 단계를 거친다는 점은 다들 잘 알고계실겁니다. 광원으로부터 온 빛이 물체의 표면에 닿고, 해당 표면에서 반사된 빛이 동공을 통해 들어와 망막에 상이 맺히며, 이것이 뇌에서 처리되어 우리는 물체를 인식할 수 있게되는거죠.

 

그래픽스에서도 비록 형태는 좀 다를지언정, 어떤 물체가 단순한 좌표의 나열에서부터 화면에 표시되는 이미지가 되기까지는 우리의 눈과 마찬가지로 여러 과정을 거칩니다.

 

오브젝트 공간에서 월드공간으로 변환, 월드공간에서 카메라 공간으로의 변환, 그리고 카메라 공간에서 클립공간으로의 변환까지 총 3번의 변환과정을 거쳐 우리의 화면에 표시되기 위한 밑작업을 수행하게 됩니다. 이러한 변환을 각각 월드변환, 뷰변환, 투영변환이라고 부릅니다.

 

월드변환, 뷰변환, 투영변환 모두 각각의 계산과정이 존재합니다만은 굳이 일일이 계산방법을 알아야 할 필요성이 있을지는 모르겠습니다. 책에서는 계산과정을 굉장히 상세하게 다루고 있지만, 엔진을 통해 접하게 될 사람에게는 굳이 그러한 복잡한 계산과정을 개념적으로 이해할 필요가 있을지 의문이군요. 다만, 이전 포스팅에서 작성한 물체의 회전, 확대/축소, 이동이 그러했 듯,  변환을 위하여 하나의 행렬이 만들어지고, 이를 오브젝트 공간 좌표에 곱하는 과정이 곧 변환과정임을 기억해주시면 되겠습니다.

 

 

월드 변환(오브젝트 공간 → 월드 공간)

물체 하나당 사용되는 좌표계는 오브젝트 공간(Object Space)라고 부릅니다. 각 엔진에서 에셋을 사용하려고 상세화면으로 들어가게되면 딱 오브젝트만 나와있는 공간이 있고, 해당 구역의 좌표는 월드와는 별개로 구성되는 걸 볼 수 있는데 해당 공간이 바로 오브젝트 공간입니다.

 

개별 오브젝트들을 월드에 배치하는 순간, 해당 오브젝트는 월드 공간에 종속되게됩니다. 아울러, 엔진에서는 해당 오브젝트 공간을 월드 공간으로 연결해주기 위한 연산을 자동으로 수행하게 되는데, 이를 월드변환이라고 부릅니다.

 

한 가지 유념해야 할 점은, 법선을 월드 공간으로 옮길때에는 오브젝트와 달리 변환에 쓰이는 행렬(누적된 선형변환 행렬 'L')를 그대로 곱해서는 안되고, 역전치행렬(L^-1)의 형태로 곱해야 한다는 점입니다. 엔진을 이용하여 디자인 하는 사람에게 큰 의미가 있을까 싶기는 합니다만은... 어찌되었건 혹시라도 직접 공간이전(space change : 하나의 공간에 정의된 물체를 다른 공간으로 옮기는 것)을 구현해야 할 경우에는 법선은 따로 계산이 필요하다는 점을 잊지 않도록 주의해야겠군요.

 

 

뷰 변환(월드 공간 → 카메라 공간)

월드공간은 여러 물체들을 놓기 위한 밑바탕일 뿐, 실제 표시를 위해서는 어떤 좌표에서 어떻게 바라본 모습을 카메라에 담을건지가 중요하죠. 이 역할을 수행하는 오브젝트를 실제로도 카메라라고 부르고 있으며, 바라볼 기준점(EYE)/방향(AT)을 정하여 월드를 바라본 모습을 카메라 공간이라고 부릅니다.

 *이때 EYE/AT을 기준으로 상단 방향을 UP으로 지칭하며, EYE/AT/UP은 곧 카메라의 좌표 계산에 사용됩니다.

 

이때 월드공간에 있는 개체들이 카메라에 담기는 모습의 형태로 계산되기 위해서 또 한번의 변환과정을 거칩니다. 이 역시도 월드변환과 마찬가지로 행렬의 곱셈 형태로 계산되죠. 

 

카메라의 한 지점에서 바라본 시선은 필연적으로 카메라를 꼭지점으로 하는 사각뿔의 형태가 되는데요. 보이는 모든걸 구현하는 것은 리소스 낭비이므로 보통은 카메라 렌즈 앞 ~ 표현할 부분까지, 표현을 끝낼 부분 ~ 무한한 뒤편의 영역까지를 잘라내게됩니다. 이렇게 잘라냈을때 나타나는 앞/뒷쪽 평면을 각각 전방 평면(near plane, n으로 표기)과 후방 평면(far plane, f로 푝)이라고 지칭합니다. 

 

또한 세상 모든 영역을 바라볼 건 아니므로, 시야각을 정하여 일부만을 카메라에 담게됩니다. 이때 등장하는 표현이 게임에서 많이 보게 되는 FOV(field of view, 시야각)입니다. 시야각을 계산할 때 y값을 기준으로 삼기때문에 fovy(FOV along Y-Axis, y축 기준 시야각)라고 부릅니다.

 

화면에 표시될 크기는 모니터의 크기에 따라 달리지므로 이 또한 정해주어야 하는데요. 이를 aspect(종횡비)라고 부릅니다. 이렇게 4가지 변수를 통해 정의되는 카메라 공간을 뷰 프러스텀(view frustum)이라고 부릅니다.

 

뷰 프러스텀 바깥에 위치한 물체는 굳이 렌더링이 필요하지 않으므로 계산단계에서 배제하는데요. 이러한 과정은 뷰 프러스텀 컬링(Culling)이라고 부릅니다. 아직 이 단계에서는 물체의 폴리곤까지 자르는 작업은 수행하지 않고,통째로 바깥으로 벗어난 물체만 배제합니다.

 

참고로 앞서 언급드린 EYE/AT/UP은 카메라의 외부 파라미터로 보는데요. 이에 대응하여, fovy, aspect, n, f의 4가지는 카메라의 내부 파라미터로 봅니다.

 

OpenGL에서 소개하는 뷰 프러스텀과 near/far plane의 개념

 

 

 

투영변환(카메라 공간 → 클립 공간)

앞서 물체의 폴리곤을 자르는 작업을 언급했는데요. 해당작업을 포함하여 카메라공간을 2×2×2  공간으로 옮겨담는 과정을 투영변환이라고 부릅니다. 사다리꼴 모양의 뷰프러스텀 상태에서는 계산이 매우 어렵기 때문에 클립 공간(clip space)으로 옮기게 되는데요.

 

이러한 클립공간의 전면부는 작고, 후면부는 넓기 때문에 2×2×2  공간으로 옮기는 과정에서 전면부에 가까운 물체일수록 좀 더 크게 변형됩니다. 이러한 변형과정은 마치 물체에 원근법이 적용된것 처럼 보이게 만들어줍니다. 아울러, 계산이 용이하도록 2×2×2의 정사각 공간을 만들었으므로, 이 영역을 벗어나 있는 (버텍스)삼각형은 이 과정에서 계산에서 배제하게 되는데요, 이러한 과정을 클리핑(clipping)이라고 부릅니다.

 

투영변환 단계는 버텍스 셰이더에 의해 이뤄지나, 클리핑 등 공간이전에 따른 행렬 계산 이후의 세부적인 작업들은 래스터라이저에 의하여 수행됩니다. 

 

 

 

 

반응형