Daily Life of BlueRose

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

컴퓨터 그래픽스 - 래스터라이저의 기능(클리핑, 뒷면제거, 뷰포트 변환, 스캔 전환)

푸른로즈 2024. 10. 16. 23:37
728x90

여는 글

래스터라이저는 포토샵에서 종종 보이던 기능인 '래스터라이즈'라는 기능을 통해서 어느정도 이름을 접해본 기억이 있다보니 아무래도 친숙하게 느껴졌습니다. 포토샵에서 래스터화 전/후가 벡터에서 픽셀로 바뀌다보니 이와 유사하게 3D그래픽스에서도 벡터그래픽을 픽셀로 바꿔주는 기능정도라고 생각이 들기도 했네요.

 

물론 래스터라이저의 가장 주요한 기능 중 하나가 해당 기능이기는 합니다만은, 2D 평면의 벡터그래픽을 픽셀로 바꿔주는 단순한 모습과는 다르게 여러가지 래스터라이저가 하는 일이 많다는 걸 새삼 깨닫게 된 챕터였습니다.

 

아... 혹시나 저처럼 래스터라이저와 픽셀셰이더의 역할을 혼동하시는 분이 계실듯하여 미리 역할을 서로 정리하자면, 파이프라인 단계상으로도 래스터라이저가 우선 작동하게끔 되어있으며 클리핑, 뒷면제거, 원근법 구현, 뷰포트 변환 및 스캔 전환 등의 기능을 수행합니다. 반면, 픽셀 셰이더는 래스터라이저를 통해 정해진 픽셀에 대하여 조명, 텍스처 등을 고려하여  각 픽셀별로 어떤 색상을 취할지를 결정해주는 요소라고 정리할 수 있겠습니다. 상호 기능이 유기적으로 연결되어있긴 합니다만은 엄연히 다른 기능을 하는 요소들입니다.

 

이번 포스팅에서는 래스터라이저의 기능들을 확인해보겠습니다.

 

클리핑(Clipping)

클리핑은 이전 포스팅에서도 다루었 듯, 클립 공간을 벗어나는 프리미티브들을 제거하여 이후 단계의 계산처리부담을 줄여주는 단계입니다. (삼각형을 기준으로)프리미티브의 정점 3개가 모두 클립공간 내부에 있다면 보존, 외부에 있다면 배제합니다. 문제는 정점 중 일부가 밖으로 나가있는 경우인데요.

 

이 경우에는 해당 정점으로 이어지는 선분과 클립공간이 만나는 지점을 기준으로 새로운 정점을 생성하고 이를 기준으로 새로운 프리미티브를 만들어낸 뒤, 바깥에 위치한 나머지는 버립니다. 

 

 

참고로, 클리핑은 GPU에서 알아서 처리해줍니다.

 

 

원근법 구현(Perspective Division)

이 과정은 클립공간을 정육면체 형태의 공간으로 재편하면서 자동으로 이뤄지게됩니다. 사각뿔대 모양의 뷰프러스텀을 정육면체 형태로 재구성하는 과정에서 뷰프러스텀 내부의 물체크기를 카메라와의 거리로 나눠 정규화를 해주는데요.

 

이러한 나눗셈을 통해 카메라 렌즈와 가까이 있는 물체일수록 상대적으로 큰 크기를 유지하고, 멀리 있는 물체는 거리에 비례하여 작아지게 됨으로써 원근법이 구현됩니다. 때문에 원근법의 구현과정을 원근 나눗셈(perspective division)이라고 부르기도 합니다. 

 

딱히 게임 엔진에서 이러한 원근나눗셈과 관련하여 특별히 조작가능한 옵션은 없는 것 같군요.

 

 

뒷면제거(Back-face Culling)

구현과정

뒷면제거는 카메라 시점으로부터 어떤 물체의 뒷부분은 별도로 구현하지 않음으로서 그래픽 부하를 줄이는 기능입니다. 뒷면제거를 위해서는 2가지 방법이 있는데요.

 

첫째 방법은 ⓐ카메라의 렌즈에서 시선방향으로 퍼지는 투영선과 ⓑ프리미티브의 법선의 두 직선에 대하여 내적을 구하는 방법입니다. 책에서는 개념적으로는 이 기능을 소개하고 있지만, 법선을 생성하고 내적을 구하려면 아무래도 복잡한지 실제 구현시에는 다른 방법을 씁니다

 

둘째 방법은 카메라의 시점에서 바라보았을 때, 프리미티브의 정점1, 2, 3의 순서가 시계방향인지, 반시계방향인지 확인하는 것입니다. 이는 기본적으로 프리미티브의 정점들이 (외부에서 관찰시) 반시계방향으로 생성되기 때문입니다. 다만 개념적으로는 이렇게 간단하더라도, 결국은 실제 판단을 위해서는 프리미티브의 정점1, 2, 3에 대하여 ⓐ정점1→2 방향의 벡터(a, b), ⓑ 정점1→3 방향의 벡터(c, d), 2개의 벡터끼리의 외적을 통해 시계방향, 반시계방향 여부를 판단해야 합니다.

 

참고로 교과서에서는 이걸 외적으로 표현하지 않고 행렬식을 계산하여 음수/양수여부를 판단한다고 써놓았더군요. 쉽게 잘 설명하던 책에서 굳이 왜 이렇게 와닿지 않게 표현했는지 모르겠습니다... (ad-bc는 행렬식이라고 부르지만, 실상은 외적을 구하는 공식으로도 쓰이죠.)

 

여튼, 벡터a를 기준으로 벡터b가 우측에 있다면 이는 시계방향이라고 볼 수 있겠습니다. 아울러 기준벡터로부터 우측에 대조군 벡터가 위치한다면 외적값은 음수가 나오며 이에 따라 뒷면으로 판정합니다. 반대로 좌측에 대조군 벡터가 위치한다면 반시계방향이며, 외적값은 양수가 나오게 되고 앞면으로 판정합니다.

 

언리얼 엔진에서의 적용

양면제거 기능은 아무래도 2가지로 나뉘는 것 같습니다. 첫째는 카메라를 기준으로 뒷면인 부분을 제거하는 기능, 둘째는 오브젝트를 기준으로 바깥면(앞면)을 구현하고, 안쪽면(뒷면)을 제거하는 기능, 이렇게 두 개의 파트로 말이죠.

 

OpenGL에서는 두 기능이 모두 기본적으로 사용된다면, 언리얼엔진에서는 전자인 카메라 기준 뒷면 제거 기능은 별도로 사용되지 않는 듯 합니다. 즉, 언리얼 엔진에서는 물체를 기준으로 뒷면제거를 하게끔만 세팅되어있어서, 뒷면제거를 수행하고 싶다면 머티리얼 부분에서 세팅해야합니다. 아래 스크린샷과 같이 Two Sided를 체크해주면 컬링기능을 꺼서, 뒷면에서도 물체의 모습을 볼 수 있습니다(꺼져있는 경우에는 뒷면에서 보는 경우에는 그냥 투명하게 처리됨). 

 

언리얼 엔진 머티리얼 부분에서 뒷면제거 on-off 설정이 가능하다

 

OpenGL과 달리 언리얼 엔진에서 이러한 차이가 발생하는데는 아무래도 메라 기준 뒷면 제거의 한계(게임에서 Back-Face Culling이 반복되면 점멸이 발생하여 그래픽이 지저분해지는 점)가 있는 점이나, 애초에 게임을 위한 엔진인 만큼, 여러 카메라가 사용되는 게임 상황에 대비하여 특정 카메라 시점 기준 Culling이 어렵다는 점이 작용한 것으로 보입니다.

 

만약 언리얼 엔진에서도 교과서에 언급된 것과 같이 '특정 물체를 반으로 잘라서 내부를 보는 효과'를 얻으려면, 블루프린트 노드 중 twoSidedSign(Input) 노드를 불러와서 -1을 곱한 뒤 이를 오브젝트의 Opacity Mask에 적용하는 것으로 구현할 수 있습니다. (그런데 생각해보니 굳이 이렇게하기보다는 차라리 처음부터 내면이 보이는 형태로 모델링을 할 것 같긴 하네요.)

 

아울러, 뒷면제거 챕터에서 제시된 기능인 z-Buffering의 경우는 다른 물체에 가려진 폴리곤을 구현 생략하는 방식인데요. 이러한 기능은 언리얼엔진에서는 Occlusion Culling이라는 이름으로 구현되고 있습니다. 덤으로, 너무 먼 거리에 있는 물체를 구현 생략하는 방식은 Cull Distance Volumes라는 이름으로 사용되고 있습니다. 

 

 

뷰포트 변환

가장 마지막으로 이뤄졌던 투영 변환에 이어, 래스터라이저에서는 3D공간을 2D모니터 내 실제 렌더링 지점으로 옮기는 뷰포트 변환을 수행합니다. 

 

대부분의 경우 게임을 전체화면으로 즐기긴 하겠습니다만은, 윈도우용 핑퐁과 같이 크기가 고정된 소형창의 형태로 제공되는 경우도 있으니 뷰포트의 크기가 항상 모니터의 크기와 같다고는 볼 수 없겠습니다.

 

언리얼 엔진에서는 편집 → 에디터 개인설정    레벨 에디터    플레이    Game Viewport Settings    새 뷰포트 해상도 순으로 이동하여 뷰포트의 크기를 직접 지정할 수 있습니다. 만약 모바일 게임을 개발하는 경우에는 아무래도 필수적으로 수정을 해줘야겠죠?

 

 

스캔 전환

마지막으로 래스터라이저의 가장 핵심적인 기능인 프래그먼트를 생성하는 기능은 스캔전환 단계에서 이뤄집니다. 엔진에서 스캔전환과 관련하여 사용자가 직접 무언가를 다루는 경우는 별로 없는 것 같습니다. 버텍스의 좌표값을 기준으로 투명도를 지정하는 등, 버텍스 셰이더와 관련된 부분이 존재하는 것과는 대조적이죠.

 

다만, 스캔전환과 관련하여 간접적으로 사용자가 다루는 부분들이 몇 있는데, 여기에는 안티엘리어싱 설정(계단현상을 줄이기), 머티리얼의 가상* 텍스처링, 묘사수준(Level Of Detail) 등이 간접적으로 영향을 미친다고 합니다만은... 딱히 스캔라인과 관련하여 조작하는 부분이 있다기보다는 개별적인 그래픽 기능들을 나열해놓은 느낌이라 썩 와닿지는 않네요. 아마 계산과정에서 래스터라이저의 처리과정에 일부 영향을 주는가봅니다.

 ※ 가상이란, 텍스처가 필요한 시점에, 필요한 만큼만 로딩하는 걸 말합니다. (나나이트, 버추얼 텍스처에서 사용)

반응형