z 버퍼 (z buffer)

다른 물체에 대해 가려지는지 판단하는 방법

2019년 06월 23일

물체의 z index 판단

3차원 공간의 물체들을 2차원 화면에 표현하려면 시선으로부터 물체들의 멀고 가까움을 알아야 합니다. 멀고 가까운 정도를 카메라 좌표계의 zz 축의 의미에서 비롯한 물체의 z index 라 합니다. 물체의 z index 를 이용해 어떤 물체가 다른 물체에 가려 안보이는지 혹은 부분만 가려져 있는지를 판단할 수 있습니다.

이를 해결하기 위해 많은 알고리즘이 존재하지만 이 글에서는 그 중 가장 직관적이면서 많은 그래픽 엔진에서 사용하는 z 버퍼 알고리즘을 알아보겠습니다.

위 그림의 각각의 평면은 각각의 픽셀에 대해 z index 를 갖습니다. 카메라 좌표계에 대해 같은 xx, yy 좌표를 갖는 평면 AA 의 지점 aa 와 평면 BB 의 지점 bb 중 화면에 보이게 될 지점은 z index 가 낮은 aa 입니다.

z index 를 사용하기 위해서는 (넓이 ×\times 높이) 만큼의 크기를 가지는 이미지 버퍼와 같은 사이즈의 z 버퍼를 준비합니다. 할당된 z 버퍼는 모든 픽셀 값을 무한대로 초기화합니다. 이후 평면의 한 픽셀의 z index 를 구하고 대응하는 z 버퍼의 값과 비교해 더 작으면 z 버퍼의 값을 평면의 z index 값으로 덮어씁니다. 아래 그림은 모든 평면에 대해 반복하면서 z 버퍼의 값이 달라지는 과정을 보여주고 있습니다.

모든 평면에 대해 알고리즘의 순서는 다음과 같습니다.

for polygon of polygons
  scanline polygon with z buffer
  calculate polygon's current pixel's z index
  if z index is smaller than z value in z buffer,
    overwrite image buffer and z buffer with current polygon's color and z index respectively.





zz 값 구하기

공간상의 평면들이 항상 카메라 좌표계의 xyxy 평면과 평행하지는 않습니다. 따라서 평면의 각 지점에 대한 zz 값을 직접 계산해야 합니다. zz 값의 계산식은 렌더링 시 물체의 투상법(projection) 에 따라 달라집니다. 이 글에서는 평행 투상(parallel projection) 과 원근 투상(perspective projection) 에 대해 각기 다른 zz 계산식을 찾아보겠습니다.

아래 식은 평면의 방정식입니다.

ax+by+cz+d=0ax + by + cz + d = 0

평행 투상의 경우 카메라 좌표계 상 평면의 각 지점이 다음과 같이 투상됩니다.

[xyz][xyzz=1]\begin{bmatrix} x \\ y \\ z \end{bmatrix} \to \begin{bmatrix} x \\ y \\ \frac{z}{z} = 1 \end{bmatrix}

스캔라인 채우기 알고리즘을 이용해 이미지 버퍼에 색을 입히는 과정은 모든 물체들이 2차원으로 투상된 이후입니다. 즉 평면의 한 지점의 투상된 2차원 벡터 (x,y)(x, y) 만을 알 수 있습니다. 평행 투상에서는 주어진 정보 xx, yy 에 대해 아래와 같이 간단히 평면의 방정식을 이용해 zz 값을 구할 수 있습니다.

z=ax+by+dcz = -\frac{ax + by + d}{c}

원근 투상의 경우 카메라 좌표계 상 평면의 각 지점이 다음과 같이 투상됩니다.

[xyz][xzyzzz=1]\begin{bmatrix} x \\ y \\ z \end{bmatrix} \to \begin{bmatrix} \frac{x}{z} \\ \frac{y}{z} \\ \frac{z}{z} = 1 \end{bmatrix}

따라서 스캔라인 과정에서 우리가 알 수 있는 정보는 xz\frac{x}{z}, yz\frac{y}{z} 입니다. x=xzx' = \frac{x}{z}, y=yzy' = \frac{y}{z} 라 하면 x=zxx = zx', y=zyy = zy' 이므로 이를 평면의 방정식에 대입해 아래와 같이 정리할 수 있습니다.

axz+byz+cz+d=0z=dax+by+c\begin{aligned} ax'z + by'z + cz + d = 0 \\ \to z = -\frac{d}{ax' + by' + c} \end{aligned}





계수 구하기

평면의 한 지점의 zz 를 구하는 식을 알아보았습니다. 이번에는 평면의 방정식 ax+by+cz+d=0ax + by + cz + d = 0 에 대한 각각의 계수 aa, bb, cc, dd 를 구하는 방법을 알아보겠습니다. 평면의 방정식에서 계수 aa, bb, cc 는 평면의 법선 벡터(normal) 의 각각의 xx, yy, zz 성분을 의미합니다.

법선 벡터는 평면에 포함된 두 개의 벡터의 외적입니다. 두 개의 벡터는 평면의 세 꼭지점을 이용해 찾을 수 있습니다. 평면의 세 꼭지점을 AA, BB, CC 라 할 때 두 개의 벡터를 AB\overline{AB}, AC\overline{AC} 로 선택하면 법선벡터는 AB×AC\overline{AB} \times \overline{AC} 입니다.

계수 dd 는 평면의 한 점 A(xa,ya,za)A(x_a, y_a, z_a) 와 법선 벡터의 성분 aa, bb, cc 를 평면의 방정식에 대입해 찾습니다.

d=(axa+bya+cza)d = -(ax_a + by_a + cz_a)





참고