578p
<Z버퍼와 Opaque>
-Z버퍼는 깊이 버퍼, Depth Buffer 등으로도 불린다
게임을 시작할 때, 한 프레임마다 배경, 캐릭터, UI, 이펙트 등이 합쳐서 나오게 된다. 그러면 이중에서 가장 먼저 그려지는 것은 무엇일까?
원론적으로 말하자면, 그리는 순서는 상당히 제멋대로라서 예측하기가 어렵다. 특정한 명령이나 Grouping으로 순서를 조정할 순 있지만(ex. Opaque - Skybox - Translucent - Post Process) 일단 기본적으로는 '계산이 끝난 녀석을 그린다'라는 원칙으로 그려지고 있으니 어떤 것이 먼저 그려질지 알수가 없다.
이 그림도 파랑색 오브젝트가 먼저 그려졌는지 빨간색 오브젝트가 먼저 그려졌는지 알 수 없다는 것이다. 그래서 '순서는 일단 상관없이 그린다'라는 기본 대전제에서부터 시작해보자.
++유니티에서는 '프레임 디버거'를 이용하면 매 프레임마다 그려지는 게임 오브젝트의 순서를 눈으로 확인 가능하다.
*뒤에 있는 오브젝트가 먼저 그려지고, 앞에 있는 오브젝트가 그려질 때
바닥이나 Skybox 등은 무시하고 진행해보자.
뒤에 있는 빨강이가 먼저 그려진 후 파랑이를 그리는 것은 문제가 없다. 이미 그려진 그림 위에 덧그리면 되는 거니깐. 이것을 'Overdraw 오버드로우'라고 한다.
*앞에 있는 오브젝트가 먼저 그려지고 뒤에 있는 오브젝트가 그려질 때
이럴 때에 문제가 생긴다. 앞뒤를 판정할 수 있는 아무런 정보가 없다면, 나중에 그려진 뒤에 있는 오브젝트가 앞에 있는 오브젝트를 덮어버릴 것이다.
이럴 경우에는 '지금 제일 앞에 그려져 있는 것은 무엇인가'라는 정보가 필요하다. 그리고 이 정보는 픽셀 단위로 존재해야 한다.
다시 정리하자면, '앞뒤 판정을 위해서 각 픽셀마다 카메라를 기준으로 가장 가까운 오브젝트의 깊이 값이 저장되어 있는 데이터 시트가 필요하다'라는 말이 된다.
이것은 당연하게도 1.000 ~ 0.000의 숫자로 나타낼 수 있다. 즉 흑백으로 표현 가능하다.
그리고 이 '깊이값'을 각 픽셀 별로 써놓은 그림을 Z버퍼(Z Buffer) 또는 깊이 버퍼(Depth Buffer)라고 한다.
+버퍼란?
그래픽 카드는 여러 버퍼를 렌더링하고 있다. Depth 버퍼, Back 버퍼, Stencil 버퍼 등 이렇게 눈에 보이진 않지만 그림으로 그려서 메모리에 가지고 있는 것을 버퍼라고 한다. 버퍼링 할 때 그 버퍼이다.
실제로 언리얼에서 깊이값을 확인해보자
뷰 모드 > 버퍼 시각화 > 씬 뎁스를 누르면 보인다. 위의 그림은 잘 안보이는데 0~1의 흑백값으로 표현된 것을 볼 수 있다. 언리얼은 유니티랑 반대인 것 같은데 가까울수록 0에 가깝고 멀어질수록 1에 가까워진다. 즉 이런 정보를 가진 버퍼가 매 프레임마다 그려지고 있는 것이다. 셰이더에서도 이 깊이값을 가져와 이용할 수 있다.
이렇게 늘 Z 버퍼가 그려지고 있어서 뒤의 오브젝트가 나중에 그려지더라도 앞의 오브젝트가 미리 써놓은 Z버퍼 값을 참조해서 그리면 앞뒤 판정은 문제가 없게 되는 것이다. 각 픽셀마다 내 앞에 누가 먼저 그려져있는지 확인하는 것이다. 깊이 버퍼를 참조해서, 자기가 뒤에 있다고 판단되는 픽셀은 그리지 않는다!
하지만 이건 알파(반투명)이 없는 Opaque(불투명) 오브젝트에 한정된 이야기다.
반투명에 대해서는 다음 글에~~~
총 정리해보자면
'기본적으로 게임 오브젝트들을 그리는 순서는 정해져 있지 않고, 오브젝트가 그려질 때마다 Z버퍼를 참고하여 앞뒤 판정을 한 후 그릴 픽셀과 그리지 않을 픽셀을 결정한다'
+만약 완전히 같은 Z값에 위치한 두 Plane이라면?
이 Plane들을 보면 겹쳐진 각 픽셀들이 매 프레임마다 서로 앞으로 나가려고 싸우게 될 것이다. 지글지글한 노이즈처럼 보이는 것을 확인할 수 있다. 이걸 'Z Fighting'이라고 부른다