Z 버퍼링
컴퓨터 그래픽스에서 Z 버퍼링(z-buffering)은 3차원 그래픽스의 이미지 심도 좌표 관리 방식이며, 일반적으로는 하드웨어적으로 처리되나 이따금은 소프트웨어로 처리되기도 한다. 어느 물체를 보이게 할지 말아야 할지에 대한 가시도 문제의 한 해결책으로 쓰이기도 한다. 화가 알고리즘은 덜 효율적이긴 하나 또다른 보편적 해결책으로 쓰이고 불투명 화면 요소를 관리할 수도 있다.
어떤 물체가 그려질 때 만들어진 픽셀의 깊이 정보(z 좌표)는 버퍼(Z 버퍼 혹은 깊이 버퍼)에 저장된다. 이 버퍼는 (x-y)의 2차원 좌표를 기준으로 해당하는 각각의 스크린 픽셀 요소들로 정렬되어 있다. 만약 다른 물체가 같은 픽셀에 그려져야 할 때, Z 버퍼링은 현재 픽셀과 새로 그려질 픽셀 중 어떤 것이 관찰자에게 더 가까운지 깊이를 비교한다. Z 버퍼에 기록되도록 새로 선택된 깊이는 이전의 깊이를 덮어쓴다. 즉, Z 버퍼는 더 '가까운 물체가 더 먼 물체를 가린다' 라는 직관적 깊이 관념을 정확하게 따를 수 있게 돕는다. 이 방식을 Z 컬링이라고 부른다.
Z 버퍼의 정밀도는 씬의 품질에 큰 영향을 미친다. 16비트의 Z 버퍼는 두 물체가 매우 가까울 때 "Z 파이팅" 혹은 스티칭이라고 하는 현상을 일으킬 수 있다. 24비트 혹은 32비트의 Z 버퍼는 더 나은 결과를 보여주지만 추가적인 알고리즘 없이는 이 문제를 완전히 해결할 수 없다. 8비트의 Z 버퍼 알고리즘은 매우 낮은 정밀도로 거의 사용되지 않는다.
Z 버퍼는 컴퓨터 게임과 같은 3D 그래픽스가 구동되는 현대 거의 모든 컴퓨터, 노트북, 모바일 기기에 사용된다. Z 버퍼는 규소 칩(집적 회로)에 하드웨어로서 구현되어 있다. 하드웨어가 아닌 소프트웨어적으로 구현된 Z 버퍼는 영화에 컴퓨터로 만들어진 특수 효과를 만들어내는 데에도 사용된다.
또한 Z 버퍼의 정보는 빛을 기준으로 렌더링된 정보로부터 섀도 매핑(shadow mapping)을 이용한 그림자 생성을 가능하게 한다.
정밀도가 조금만 줄어들더라도 Z 버퍼의 거리 정보가 균일하게 퍼져있지 않고 조밀한 경우에 씬의 품질에 문제가 발생할 수 있다. 거리가 가까울수록 거리가 먼 값보다 더 정밀하고, 따라서 가까이에 존재하는 물체가 더 잘 그려진다. 일반적으로 이 현상은 바람직하지만 가끔 물체가 더 멀리 있는 것처럼 보이게 한다. 더 균일한 정밀도를 위해 고안된 Z 버퍼링의 응용은 W 버퍼링이라고 불린다.
씬을 그리기 전에 먼저 Z 버퍼는 보통 1.0으로 초기화될 필요가 있다. 왜냐하면 이 수치가 0.0부터 최대 1.0까지의 깊이 값으로 정의되기 때문이다. 즉, 뷰 프러스텀 내에 이 수치를 벗어나는 물체는 존재할 수 없다.
Z 버퍼의 개발에는 에드윈 캣멀이 가장 많은 기여를 했지만, Wolfgang Straßer가 1974년에 이미 이 기법을 고안해냈다.
최신(1995-2005) 그래픽 카드에서, Z 버퍼는 메모리 대역폭을 상당히 많이 사용한다. Z 버퍼링의 동작 비용을 줄이기 위해 다양한 기법들이 개발되어 왔다. 예를 들면 무손실 압축(메모리 대역폭을 더 사용하는 것보다 리소스를 압축, 압축 해제하는 편이 비용이 덜 든다)과 간단하게 한 프레임은 양수, 다음 프레임은 음수로 사용하는 트릭(부호를 가진 숫자로 깊이값을 교묘하게 체크해서 프레임 사이의 Z 값 초기화를 건너 뛸 수 있다)으로 굉장히 빠르게 하드웨어의 Z값을 초기화할 수 있는 방법이 그것이다.
Z 컬링은 깊이 정보에 기반하여 픽셀을 일찍 제거해, 가려진 면을 렌더링 할 때 드는 비용을 줄여 성능 향상을 가져올 수 있는 기법이다. 픽셀에 기록된 깊이가 물체의 깊이와 비교되어 물체가 가려지는지 아닌지 자연스럽게 알 수 있기 때문에 Z 버퍼링을 수행할 때에 당연하게 따라오는 결과이다.
Z 버퍼를 사용하면, 픽셀의 깊이를 통해서 그려져야 할지 아닐지를 알 수 있으므로 조명 계산이나 텍스쳐링과 같은 모든 과정을 건너 뛸 수 있을지 판단 할 수 있다. 또한, 컬링된 픽셀에 대해서는 오래걸리는 픽셀 셰이더 계산 또한 건너 뛸 수 있다. 따라서 Z 컬링은 fillrate(필 레이트), 조명 연산, 텍스쳐링 혹은 픽셀 셰이더가 주된 병목일 경우에 성능을 향상시킬 수 있는 좋은 해결책이 될 수 있다.
Z 버퍼링이 정렬되지 않은 모델들을 그릴 때, 화가 알고리즘을 거꾸로 사용하여 뎁스의 오름차순으로 폴리곤들을 정렬하는 것은 각 스크린 픽셀이 더 적은 횟수로 그려지도록 유도할 수 있다. 이것은 필 레이트가 제한적인 씬을 많은 overdraw를 통해 그려야 할 때 성능 향상을 가져온다.하지만 Z 버퍼링과 함께 사용하지 않을 때 다음과 같은 많은 문제를 겪을 수 있다:
따라서, 화가 알고리즘을 거꾸로 사용하는 방법은 많은 리엔지니어링 없이는 Z 컬링 대신 사용될 수 없으며 Z 컬링의 최적화하는 데만 사용될 수 있다. 예를 들어 x/y 위치와 z 깊이를 통해 폴리곤이 나뉘어져 경계선이 생기고, 이로써 두 개의 폴리곤이 서로 겹칠지 아닐지에 대해서 빠르게 결정하도록 도울 수 있다.
렌더링될 카메라 공간에서 깊이값의 범위는 보통 formula_1 와 formula_2 사이의 formula_3 값으로 정의된다. perspective(원근) 투영을 거친 후 formula_3, 혹은 formula_5값은 다음과 같이 정의된다:
formula_6
orthographic(직교) 투영을 거친후 formula_3, 혹은 formula_5값은 다음과 같이 정의된다:
formula_9
Z값이 카메라 공간에서 새로운 Z값보다 더 과거의 값일 경우 가끔씩 formula_10 혹은 formula_11로 쓰인다.
formula_5값은 보통 -1의 formula_1 plane과 1의 formula_2 plane 사이의 -1에서 1 사이의 값으로 정규화된다. 이 범위 밖의 값은 뷰 프러스텀 내에 존재하지 않고, 그려지지 않는다
이러한 값들은 일반적으로 고정소수점 형태로 하드웨어 그래픽 가속기의 Z 버퍼에 저장된다. 먼저 다음과 같은 식 :
formula_15
을 통해서 formula_16와 같은 형태로 [0,1]의 범위 내의 적절한 값으로 정규화된다.
그 다음, 상단의 공식은 formula_17 와 같이 곱해진 후 반올림되어 정수로 표현된다. d는 Z 버퍼의 깊이로, 일반적으로 16, 24, 32 비트로 표현된다 :
formula_18
이 공식은 Z 버퍼 해상도를 계산하기 위해 다음과 같이 파생되어 변환될 수 있다. (앞서 말한 정밀도가 이것이다) 상단 formula_19의 역함수로:
formula_20
where formula_17
카메라 스페이스의 관점에서 Z 버퍼의 해상도는 정수가 저장되는 Z 버퍼 상에서 작은 값이 점진적으로 변하는(1 혹은 -1) 증분의(incremental) 양상을 가진다. 따라서 해상도 값은 formula_5의 식에서 formula_3로 유도될 수 있다:
formula_24
카메라 스페이스 관점에서 상단의 formula_19를 formula_5로 대체해 표현하면:
formula_27
formula_28
formula_29
~ formula_30
이 식은 formula_5값이 formula_1 플레인 근처에서 더 조밀하게 모여있는 값을 가진다는 것을 보여준다. 그래서 카메라에 더 가까운 값일수록 더 정밀한 결과를 보여준다. formula_33 비율이 작을수록, 멀어짐에 따른 정확도는 더 낮아진다. 그래서 formula_34 플레인을 너무 가깝게 설정하는 것은 가까운 물체들에 대해서도 바람직하지 못한 렌더링 결과를 보여준다. 따라서 formula_34 플레인은 카메라에 가깝게 설정하는 것 보다, 목표 물체의 Z 값의 적절한 정밀도를 위하여 물체에 가깝도록 설정하는 편이 좋다.