Unity 렌더링 순서 정렬 이해하기
제대로 알지 못하면 헤어날 수 없는 렌더링 순서 지옥
Unity를 사용하여 게임을 제작하다 보면, 한번 쯤은 객체의 렌더링 순서 문제로 인해 골머리 앓는 경우를 겪게 됩니다. 특히 2D 기반 게임의 경우엔 렌더링 순서 제어 작업은 개발 중에도 항상 주의를 기울이고 신경써야 하는 필수 요소 중 하나이죠. 그런데 이러한 렌더링 순서에 관련한 이슈가 생겼을 때, 보통 하나를 해결하면 다른 하나가 문제가 발생하고 그 문제를 해결하면 또 새로운 문제가 발생하여 꼬리에 꼬리를 물고서 이슈가 지속되는 경우가 많습니다. 이는 엔진의 렌더링 순서 정렬에 대한 충분한 이해가 없이, 당장 닥친 부분의 이슈만 해결하려 하기 때문입니다. 이 이슈가 우리를 끊임없이 잡아 끌어내리는 개미 지옥으로 두지 않으려면, Unity의 렌더링 순서 정렬에 대한 확실한 이해가 필요합니다.
먼저 Opaque, 그 다음 Tranparent
우선 반드시 숙지해야 할 것은 아래 내용입니다:
Opaque 그룹에 속한 것부터 먼저 그리고, 그 다음에 Tranparent 그룹에 속한 것을 그린다.
여기서 렌더 큐 인덱스가 2500까지는 Opaque 그룹, 2501 이상인 경우는 Tranparent 그룹에 속합니다. 다시 말해, 2500번까지의 Opaque 그룹에 속한 지오메트리들은 2501번부터 그 이후의 큐 인덱스를 갖는 Tranparent 그룹에 속한 지오메트리들보다 ‘어떤 정렬 요소와 관계없이’ 먼저 그려집니다. 이 사실을 제대로 잘 인지하고 있지 않은 분들이 생각보다 많습니다. 이 기본 룰을 잊지 않도록 해야 합니다.
렌더 정렬 요소와 우선 순위
그럼 이제 앞에서 언급한 내용을 바탕으로, Unity에서 제공하는 여러 정렬 요소들을 더하면 다음과 같은 그림이 그려집니다:
그림이 복잡해 보일수도 있지만, 사실 내용은 간단합니다. 그림은 위에서 아래 방향으로 우선 순위를 가지고 지오메트리 정렬이 일어나는 모습을 표현합니다. Opaque 그룹의 지오메트리들이 가장 먼저 그려지고, 그 다음에 Transparent 그룹의 지오메트리들이 그려지며, 각 그룹 안에 존재하는 지오메트리 간의 순서 정렬은 여러 정렬 요소들에 의해 이뤄집니다. 각 정렬요소는 상대적인 우선순위가 있어 그 순서대로 적용되는데, 그림에서와 같이 각 그룹의 위쪽에 있는 정렬 요소가 상대적으로 우선순위가 높습니다. 만약 두 지오메트리가 상위 정렬 요소에 대해서 동일한 순위을 갖는 상태라면, 그 다음 하위 정렬 요소 값을 비교하여 드로우 순서를 정하게 됩니다. 예를 들어, Transparent 그룹에 속한 두 지오메트리가 같은 Sorting Layer/Order in Layer 값을 가진다면, 그 다음 정렬 요소인 Render Quere 기준으로 정렬하게 되고 이것마저도 같은 값이라면 Camera Sorting 및 엔진 내부 동작에 의해 순서가 결정됩니다.
그럼 각 정렬 요소들에 대해서 간단히 한번 살펴보겠습니다:
Sorting Layer(SL)/Order in Layer(OiL)
제일 높은 우선 순위의 정렬 요소는 바로 Sorting Layer(SL)/Order in Layer(OiL) 입니다. 먼저 SL값이 주어지고, 같은 레이어 안에서 OiL값을 다르게 주어서 동일 레이어 에서의 추가 정렬이 가능합니다.
참고로, SL/OiL은 원래 2D 기반 게임에서 Tranparent 기반 객체들을 제어하기 위한 정렬 요소입니다. 따라서 일반적인 메시 렌더러에서는 이 정렬 요소를 기본적으로 노출하지 않습니다. 그럼에도 불구하고, 만약 일반적인 불투명 지오메트리 메시 렌더러에 명시적으로 SL/OiL값을 설정한다고 하면, 역시나 가장 높은 정렬 순위 적용을 받습니다.
Sorting Group
Unity 게임오브젝트에 Sorting Group 컴포넌트를 추가하면, 해당 컴포넌트를 가진 오브젝트를 포함한 하위 객체들을 단일 Sorting Layer/OiL 로 묶어서 정렬하며, 하위에 추가로 중첩된(nested) Sorting Group을 둘 수도 있습니다. SL/OiL을 그룹화하는 것일 뿐이기 때문에, SL/OiL 정렬요소와 우선순위는 같습니다.
참고로, 한 Sorting Group 내에 속한 하위 지오메트리 간에는 전혀 다른 정렬 규칙을 가지게 됩니다. 구체적으로 말하자면, 렌더 큐 > 그룹 내의 상대적 SL/OiL > 게임오브젝트 하이어라키 순의 우선순위를 가지게 됩니다. 하지만, 사실 이 부분은 Sorting Group의 용도를 제대로 알고 사용한다면 굳이 마주칠 상황은 아닙니다. 다만, 잘못하면 혼란을 겪을 수 있는 부분이기에 언급하였습니다.
Render Queue
머티리얼에 렌더 큐 인덱스를 변정하여 렌더링 순서를 변경할 수 있습니다. 특별한 경우가 아니라면, 셰이더 코드 내에서 지정한 기본 렌더 큐 인덱스에서 벗어난 값을 설정할 필요는 거의 없습니다.
Camera Sorting
Unity는 카메라 기준에 따라 지오메트리들을 정렬합니다. Tranparent 그룹에 대해서는 지오메트리를 뒤에서 앞(back-to-front) 순으로 정렬합니다. 그리고 Opaque 그룹에서는 기본적으로 앞에서 뒤(front-to-back)로 정렬합니다. 참고로, HSR 기능을 갖는 특정 GPU들은 거리 기반 정렬이 의미가 없기 때문에, 그런 경우에 한해서는 엔진 내부에서 거리 정렬을 수행하지 않습니다.
Engine Internal
최종적으로 엔진 내부 수준에서 드로우 순서를 결정합니다. 앞서 Camera Sorting에서 언급한 특정 GPU에 대한 예외처리나 렌더링 효율을 위한 동적 배칭 처리 등 여러 상황에 따라 렌더링 순서 제어를 수행할 수 있습니다.
지금까지의 각 정렬 요소에 대한 더 자세한 내용은 Unity 메뉴얼을 통해서 반드시 확인하시기 바랍니다.
마치며
지금까지 Unity에서 렌더링 순서 정렬을 어떤 방식으로 처리하는지 전반적으로 살펴보았습니다. 이 글 처음에 언급했지만 제대로 이해하지 못한 채 닥친 문제를 해결하기에 급급하다간 개미 지옥에서 헤어나올 수 없습니다. 현재 그리고 앞으로도 충분히 겪게 될 렌더링 순서 정렬 이슈를 헤쳐나가는 데에 이 글이 조금이나마 도움이 되길 바랍니다.
레퍼런스
Unity - 2D Sorting
Unity - Sorting Groups
Unity - Camera.opaqueSortMode