유니티 엔진에서 Alpha Blending 문제 및 원리 이해 - Whitmem
유니티 엔진에서 Alpha Blending 문제 및 원리 이해
게임 개발 및 엔진
2026-01-18 23:02 게시 5603b971f6c47c7b5af1

0
0
24
이 페이지는 외부 공간에 무단 복제할 수 없으며 오직 있는 그대로 게시되며 부정확한 내용을 포함할 수 있습니다. 법률이 허용하는 한 가이드 라인에 맞춰 게시 내용을 인용하거나 출처로 표기할 수 있습니다.
This page is not to be distributed to external services; it is provided as is and may contain inaccuracies.
유니티에서 본격적으로 개발을 진행해보려고, Hair 쉐이더를 구현하던 도중에 한 가지 문제에 봉착했다. 바로 Alpha 문제이다.
물리 기반 렌더링이 아닌 실시간 게임 처리를 목표로하는 일반적인 3D 그래픽스는 예전부터 알려진 파이프라인을 기반으로 3D 객체들을 렌더링한다.
3D 공간에 있는 객체를 2D에 투영하기 위해 어떤 객체가 카메라에 제일 가까운지 판별하는 과정이 필요하고, 최종적으로 카메라에 제일 가까운 객체만 픽셀에 채워진다.
그 과정은 깊이 테스트계산을 통해 판별되는데 이 작업의 모든 특징은 객체가 불투명하다는 전제하에 구현되기 때문에 기본적으로 투명 객체를 겹쳐 그릴 수 없다는 문제가 존재한다.
먼저 일반 불 투명 객체 그리는 과정를 살펴보자.
a 객체와 b 객체가 같은 시점에 겹치게 보인다고 할때, 실제 3D 공간에서는 왼쪽과 같이 존재한다. a, b 객체가 서로 불투명한 경우에는 반드시 정렬할 필요가 없다. 깊이 버퍼를 통해 앞에 그릴 수 있는지만 확인하면 되기 때문이다.
즉 CPU에서 a를 먼저 그리고 b를 그린 경우, a의 깊이가 먼저 깊이 버퍼 텍스처에 저장되고, b를 그릴 때 a 깊이 보다 카메라에 가까운지 확인 후 그리면 된다.
한편 CPU에서 호출하는 순서를 바꿔 b 객체가 먼저 그려졌더라도, a를 그릴 때 b 깊이보다는 뒤에 있을 것이므로 해당 픽셀은 그리지 않으면 된다.
따라서 객체를 반드시 정렬할 필요 없이 아무렇게 호출하여도 정상적으로 그려지고, 심지어 객체가 겹쳐있더라도 픽셀 단위로 깊이 버퍼를 확인하기 때문에 어느 표면이 앞에 있어야 하는지 판별할 수 있다.
즉 객체가 어떤 모습으로 하고 있던 최상위에 있는 표면인지 제일 효과적으로 빠르게 검사할 수 있다.
이 방법을 사용하지 않는다면 메시가 서로 겹쳐보이거나, 다른 객체가 화면 맨 앞에 나오거나, 엉킬 수 있고 그렇다고 직접 픽셀을 하나 하나 화면 앞에 가까운 것을 정렬하며 찾아내기에는 실시간 렌더에서는 불가능할 정도의 시간 복잡도가 발생한다.
그렇기 때문에 현재까지 그려진 메시들의 깊이를 메모리에 업데이트해가면서 현재 인풋으로 들어온 객체를 화면에 그릴 것인지, 말 것인지를 결정하는 것이다. 즉, 최댓값을 O(n)으로 구하기 위해 변수에 현재 까지 조회한 최댓값보다 큰 경우에만 업데이트하는 '최댓값 구하기'와 100% 동일하다.
이것이 깊이 버퍼의 기본적인 원리인데, 문제는 객체가 있다, 없다로 나누기 때문에 불투명 객체는 있다고 판별할 수 밖에 없는 것이다.
이런 경우 어떤 문제가 발생할까?
임의로 생성한 객체 3개를 투명하게 나열한 것이다. 근데 위 사진을 보면 뭔가 이상하다. 객체의 순서가 어긋나고, 맨 뒤에 있는 평면이 제일 앞에 있는 것 처럼 보인다.
즉 정상적으로 보일때는 위와 같아야 한다. 이러한 문제가 발생하는 이유는 반투명으로 그리면서 객체가 그려지는 순서가 매우 중요해졌기 때문이다. 아까 분명 불투명 객체를 렌더링할 때는 순서 관련 없이 제일 최상단에 그릴 것만 찾아내면 된다고 하였다. 하지만 투명 객체는 존재는 하지만, 뒤에 다른 객체가 겹쳐서 그려져야하므로 뒤에 있는 객체가 절두되면 안된다. 즉 이미 최상단에 어떤 투명 객체가 있더라도 투명 객체 뒤에 또 다른 객체를 렌더링해야 한다. 그런데 기존 깊이 버퍼 방법으로 그려버리면 아래와 같은 문제가 발생한다.
위와 같이 알파 객체가 두 개 있다고 할 때, alpha 0.5짜리가 먼저 그려진다고 생각해보자. A의 깊이가 깊이 버퍼에 그려질 것이고, 그 다음 alpha 0.6이 그려지면 정상적으로 덮어씌워져서 그려질 것이다.
alpha 0.5(a)가 그려지고, alpha 0.6(b)가 그려지는 건 지금 흐름상 당연하다. a가 b보다 카메라에 멀기 때문이다. 먼 것을 먼저 그려야 b를 그릴때 합성할 수 있다.
반면 드로우 콜을 날릴 때 alpha 0.6(b)먼저 출력했다고 가정해보자.
0.6은 카메라에 제일 가깝다. 아무것도 안그려진 상태에서는 당연히 잘 그려지겠지만, 그 이후가 문제이다. alpha 0.5짜리 a 객체를 그리려고 할 때 이미 앞에 있는 0.6 b가 그려졌기 때문에 a를 그리지 않게 된다.
즉 이렇게 중간에 있는 객체가 먼저 그려져버리면 첫 번째 객체를 렌더링 할 때는 그려지지 않게 되어버리는 것이다. 그렇다고 깊이 버퍼를 끄면 될까?
원래는 아래처럼 렌더링이 되어야 하는데, 위 사진처럼 이상하게 렌더링된 것을 볼 수 있다. 이번에는 깊이를 검사하지 않기 때문에 그려지는 순서가 항상 다를 수 있다. 맨 뒤부터 그려지면 정상적으로 그려지겠지만, 맨 앞부터 그려지면 이미 앞에 객체가 있음에도 불구하고 앞에 있는 것 처럼 알파 생성이 합쳐서 그려진다. 즉, 아래 객체 처럼 떨어져있기 때문에 색상 블랜딩이 되면 안되는 부분이, 맨 뒤에 있는 객체가 앞에 있는 것 처럼 렌더링되어 색상이 섞여버리는 문제가 종종 발생할 수 있다는 것이다.
보면 알 수 있겠지만 어떻게 렌더링되든 뒤에 있는 객체가 투명하게 비춰보이긴 한다.
하지만 문제는 알파 값은 투명도 뿐만이 아니라, 순서에 따라서 색상 비율이 달라진 다는 것이다.
위 두 사진은 서로 다른 투명도를 방향을 바꿔서 봤을 때 사진을 나타낸 것이다. 보면 알 수 있다시피 어떤 객체가 앞에 있느냐에 따라서 색의 강도에 차이가 있는 것을 볼 수 있다. 즉 투명도가 서로 다른 객체를 순서를 바꿔 그리면 여전히 투명하게 비추긴 하겠지만 색상이 비율이 엉망이될 수 있다는 것이다.
원래는 이렇게 렌더링되어야 하는 객체의 순서를 강제로 바꿔보면,
즉 뒤의 객체 색상이 더 강조되어버리는 문제가 발생한다. 이러한 문제는 알파 값의 차이가 심할 수록 더 크게 느껴진다.
극단적으로 뒤에 있는 객체의 알파를 1로 하고, 앞의 알파를 약 0.1로 했을 때, 앞의 투명한 객체를 먼저 그려버리면, 뒤에 불투명한 객체를 그릴 때 그 위에 그려지기 때문에, 투명한 부분이 사라진다. 즉 알파 비율도 순서가 매우 중요한데, 깊이 버퍼를 꺼버리니 앞에만 그려도 되는지 여부가 보장되지 않아, 뒤 객체가 앞을 가려버리는 현상이 발생하는 것이다.
이 문제를 해결하기 위해, 유니티 등 엔진에서는 객체와 카메라 사이의 거리를 계산하여 어떤 객체를 먼저 그릴 것인지 정렬후에 순서대로 호출한다. 하지만 이 방법에도 한계가 있는데, 이는 객체 단위로 순서를 정렬할 뿐이고, 객체의 형상이 복잡하여 다른 객체를 겹치거나 일부라도 삐져나오는 경우 그 부분만 앞에 있는 것 처럼 보이는 비현실적인 문제가 발생하게 된다.
즉 이런 메시들이 있을 때, 긴 메시 객체가 카메라에 제일 가까우므로 제일 마지막에 그려진다. 그런데 막상 저기 멀리 있는 객체부분에서는 투명한 객체들이 카메라에 더 가까우므로 그리는 순서가 반대가 되어야 한다. 객체 순서는 각 표면, 픽셀 단위의 순서까지 보장하지는 못하기에 겹치거나, 형상에 따라 순서가 뒤집어질 수 있다는 것이다.
픽셀 단위로 순서를 정렬하면 되겠지만, 보통 게임 개발은 리얼 타임으로 렌더링해야 하기 때문에 현실적으로 불가능하다.
대안인 방법으로 디더링 방식이 사용되는데, 불투명한 opaque 객체로 취급하되 구멍을 뚫어 밀도로 투명도를 표현한다. 즉 착시 효과를 사용하는 것인데,
현재까지 알려진 객체의 블렌딩 문제를 거의 해결한다는 이점이 있다. 다만, 디더링은 착시 효과이기 때문에, 시각적으로 약간 불편하다는 문제가 있다.
(찾아보니 디더링은 특허 관련 얘기가 있던데, 조사가 필요해보인다. 이 게시글에서는 구현 방법에 대해서는 언급하지 않는다.) 대부분의 AAA 게임들이 카메라 절두체에 벗어나 서서히 가릴 때 디더링을 사용하는 것으로 보인다.
댓글 0개
댓글을 작성하는 경우 댓글 처리 방침에 동의하는 것으로 간주됩니다. 댓글을 작성하면 일회용 인증키가 발급되며, 해당 키를 분실하는 경우 댓글을 제거할 수 없습니다. 댓글을 작성하면 사용자 IP가 영구적으로 기록 및 부분 공개됩니다.
확인
Whitmemit 개인 일지 블로그는 개인이 운영하는 정보 공유 공간으로 사용자의 민감한 개인 정보를 직접 요구하거나 요청하지 않습니다. 기본적인 사이트 방문시 처리되는 처리 정보에 대해서는 '사이트 처리 방침'을 참고하십시오. 추가적인 기능의 제공을 위하여 쿠키 정보를 사용하고 있습니다. Whitmemit 에서 처리하는 정보는 식별 용도로 사용되며 기타 글꼴 및 폰트 라이브러리에서 쿠키 정보를 사용할 수 있습니다.
이 자료는 모두 필수 자료로 간주되며, 사이트 이용을 하거나, 탐색하는 경우 동의로 간주합니다.