[게임수학] 10-2. 깊이 값

2026. 2. 28. 19:40·게임수학
728x90

→ 이 글은 「이득우의 게임 수학」을 바탕으로 작성했습니다.

■ 깊이 값

3D 공간의 물체들을 화면이라는 2차원 평면에 투영하면, 화면 좌표에는 $x$와 $y$정보만 남게 된다. 이 상태에는 어떤 물체가 더 앞에 있고 뒤에 있는지를 구분할 수 없어 결국 나중에 그려진 물체가 화면의 앞에 보일 수밖에 없다.

 

따라서 물체가 카메라로부터 얼마나 떨어져 있는지 파악할 수 있는 데이터가 필요한데, 이를 깊이$^{Depth}$값 이라 한다.

[3차원으로 확장된 NDC 영역]

2차원 평면의 NDC에서 깊이 값을 추가하면 3차원 영역으로 확장된다. 깊이 값의 범위는 동일하게 $[-1,1]$이다.

[카메라에 설정한 절두체]

NDC영역과 마찬가지로 카메라에 부여한 시야각은 깊이값과 무관하기 때문에 근평면$^{Near plan}$과 원평면 $^{Fraplane}$이라는 추가 속성을 부여해야 한다.

  • 사각뿔 영역을 근평면과 원평면으로 잘라주면 위 그림과 같은 형태가 나오게 되는데 이를 절두체$^{Frustum}$라 한다.

 

1. 원근 투영 행렬에 깊이값 추가

$$ P \cdot \vec{v}=\begin{bmatrix}\frac{d}{a} & 0 & 0 \\0 & d & 0 \\0 & 0 & -1\end{bmatrix}\begin{bmatrix}v_x \\v_y \\v_z\end{bmatrix}=\begin{bmatrix}\frac{d}{a}\, v_x \\d\, v_y \\- v_z\end{bmatrix} $$

[원근 투영 행렬]

앞서 구한 3X3 행렬에서 깊이 값을 계산하는데 필요한 값을 추가하기 위해 3행을 4행으로 옮기고, 3행은 깊이 값을 구하는 용도로 변경하자.

[깊이값을 계산하기 위한 미지수 추가 - 1]

 

깊이 값을 계산하는데 사용하는 3행은 4개의 미지수$i,j,k,l$로 지정했다.

하지만 깊이 값은 카메라 전방 향향($z$축)의 거리만을 의미한다. 따라서 동일한 $z$값을 가지는 점들은 $x, y$위치와 관계없이 같은 깊이를 가져야 한다.

$$ z′=ivx+jvy+kvz+l $$

만약 깊이값을 계산하는데 $v_x$와 $v_y$가 포함된다면 깊이값이 $x,y$에 따라 달라진다는 의미이다. 그러므로 깊이 계산식에서는 $v_x,v_y$가 포함될 수 없으며 원근 투영의 3번째 행에서 $i,j$는 0이 된다.

[깊이값을 계산하기 위한 미지수 추가 - 2]

여기서 두 미지수의 값을 얻기 위해 근평면과 원평면의 값을 사용하자.

  • 카메라로부터 근평면까지의 거리 $= n$
  • 카메라로부터 원평면까지의 거리 $= f$

카메라로부터 $n$만큼 시선 방향으로 이동한, 근평면 상에 위치한 점의 뷰 공간 좌표는 $(0,0,-n,1)$이 된다.

  • 이는 깊이 값의 시작지점이기 때문에 NDC좌표 $(0,0,-1)$에 대응.
  • 동일하게 뷰 공간의 원평면상의 좌표는 $(0,0,-f,1)$인데 이는 깊이 값의 끝 지점이기 때문에 NDC$(0,0,1)$에 대응된다.

원근 투영 행렬에 뷰 공간의 점을 곱한 결과는 클립 좌표가 된다. 근평면의 점을 $P_1$, 원평면의 점을 $P_2$라 한다면,

아직 $k,l$값을 모르기 때문에 클립 좌표의 세 번째 요소를 직접 계산할 수 없다.

$$ P_1\cdot P_{near} = (0,0,-kn + l , n) \\ \ \\ z_{ndc} = \frac{-kn + l}{n} $$

하지만 근평면은 NDC에서 $z = -1$에 대응되어야 하므로,

$$ \frac{-kn + l}{n} = -1 $$

이다.

 

NDC는 클립 좌표를 마지막 요소인 $w$로 나눈 값이므로, $w = n$ 일 때 NDC가 $-1$이 되기 위해서는 클립 좌표의 $z$값이

$$ z_c = -n $$

이어야 한다. 따라서, 근평면의 클립 좌표는 $(0,0,-n,n)$이 되고, 원평면의 클립 좌표도 동일한 방식으로 $(0,0,f,f)$가 되어야 한다.

[뷰 공간의 좌표와 NDC값의 비교]

따라서 위와 같은 식을 얻을 수 있다. 여기서 두 행렬의 3행과 뷰 공간의 점을 내적하면 다음 두 식을 얻을 수 있다.

$$ -kn + l = -n \\ -kf + l = f $$

$n,f$는 카메라에 설정된 상수이므로, 두 식을 서로 빼, $l$을 소거한 후 $k$값을 구하면 아래와 같다.

$$ k = \frac{-(n + f)}{(-n + f)} = \frac{n + f}{n - f} $$

여기서 구한 $k$를 대입해 $l$을 계산하면,

$$ l = \frac{2nf}{(n-f)} $$

따라서 깊이 값을 산출해주는 최종 원근 투영 행렬 $P$는 다음과 같다.

■ 원근 보정 매핑

원근 투영 행렬에서 깊이 값을 추가해 문제를 해결했지만, 아직 한 가지 문제가 남아있다.

[기존 텍스처 매핑의 문제점]

각 픽셀의 무게중심좌표를 구한 뒤, UV좌표를 계산하고 텍스처 매핑을 구현했지만, 평평하게 그려져야 할 눈과 눈썹이 처지거나 올라가 있다.

 

이는 원근 투영이 “선형 변환”이 아니어서 생기는 문제인데, 왜 이런 상황이 나오는지 자세히 살펴보자.

[시야각 사이에 걸쳐 있는 두 점의 투영 결과]

투영하기 전의 두 점$(P_1, P_2)$가 카메라 시야각에 걸쳐있다면, 투영한 점$(N_1, N_2)$의 $x$좌표값은 $-1, 1$이 된다.

  • 카메라 정면에 위치한 $P_3$는 투영 후 투영 평면의 정 중앙에 위치한다.

투영 후 $N_1$과 $N_2$를 이어 선분을 생성하면, 선분의 중앙에 위치한 $N_3$의 무게중심좌표는 0.5가 된다.

하지만 투영 전, 선분$P_1P_2$ 내에 위치한 점 $P_3$의 무게중심좌표는 0.5에 위치하지 않는다.

[뷰 공간의 선을 수평으로 조정]

원근 투영은 다음과 같이 계산된다.

$$ x_{ndc} = \frac{x}{-z} $$

즉, 좌표를 나누는 연산이 포함되는데, 이 나눗셈 때문에 선형 관계가 유지되지 않는다. 깊이가 다르면 선형 관계가 깨진다는 의미이다.

 

3D 공간에서 선형 보간된 점은 $P = \alpha P_1 + \beta P_2$의 형태이지만, 투영 후에는 $N = \frac{P}{w}$가 되므로 결국,

$$ \frac{\alpha P_1 + \beta P_2}{w} \ne \alpha \frac{P_1}{w_1} + \beta\frac{P_2}{w_2} $$

가 된다. 즉, 투영 전 무게중심좌표와 투영 후 무게중심좌표가 서로 다르게 되므로 이 차이로 인해 텍스처 왜곡이 발생하는 것이다.

 

1. 투영 보정 보간

이를 수정하기 위해선 “투영 전 무게중심좌표”를 사용해야 하고, NDC의 무게중심으로부터 투영 전의 무게중심좌표를 계산하는 것을 투영 보정 보간(Perspective corrention interpolation)이라 한다.

 

NDC의 무게중심좌표를 투영 전의 무게중심좌표로 돌려주는 계산식을 유도하기 위해 반비례 함수 $y = -\frac{1}{x}$가 가진 성질을 보자.

[반비례 함수 그래프]

함수 $y = -\frac{1}{x}$에서 $x = 2,4,6$에 대응되는 값은 각각 아래와 같다.

$$ -\frac{1}{2}, -\frac{1}{4}, -\frac{1}{6} $$

$x$축에서 가운데 위치한 4는 2와 6의 정확한 중간에 있으므로 선형 보간의 기본 형태에 의해 다음과 같이 표현할 수 있다.

$$ 4 = a\cdot 2 + (1-a)\cdot 6 $$

이를 정리하면,

$$ 4 = 2a + 6 - 6a \\ 4 = 6 - 4a \\ a = \frac{1}{2} $$

즉, 4의 무게중심좌표는 0.5이다.

 

▼ 선형 보간식의 의미

예를 들어 2와 6가이의 어떤 값을 표현하고 싶다면, 그 값은 두 점의 일정 비율로 섞어서 나타낼 수 있다. 이는 일반적으로,

$$ x = ax_1 +(1-a)x_2 $$

의 형태로 두며, 여기서 $a$는 두 점 사이의 위치 비율을 의미한다.

보간을 할 때 가중치의 합은 항상 1이어야 하므로 $a + (1-a) = 1$이 되도록 정의한다. 이 식이 바로 선형 보간의 기본 형태이다.


 

이번엔 4에 대응하는 y값 $-\frac{1}{4}$의 무게중심좌표를 구해보자. 동일하게 선형 보간식을 사용하면,

$$ -\frac{1}{4} = a\cdot -\frac{1}{2} + (1-a) \cdot -\frac{1}{6} $$

가 되고, 위 식을 정리하면 $a = 0.25$가 된다.

여기서 살펴봐야 할 점은,

  • $x$축에서 2와 6의 중간인 4의 보간계수는 0.5 이다.
  • $y$값에서 $-\frac{1}{2}$와 $-\frac{1}{6}$ 사이에서 $-\frac{1}{4}$이 되도록 만드는 보간계수는 0.25이다.

$$ a_x = 0.5 \ \ \ne \ \ a_y = 0.25 $$

선형 함수라면 두 보간계수가 동일해야 하지만, 반비례 함수에서는 그렇지 않다.

 

만약 $y$축의 무게중심좌표 0.25로부터 $x$축의 무게중심좌표 0.5를 계산해 주는 식을 찾을 수 있다면, 이를 응용해 투영 전 무게중심좌표를 계산할 수 있을 것이다.

 

2. 투영 보정 보간식 유도

$y$축에서의 무게중심좌표를 $q_1, q_2$로 지정하고, 이를 사용해 $y$축의 두 점 $y_1, y_2$ 사이의 점 $y'$을 구하는 수식을 정리하자.

$$ y ' = q_1 \cdot y_1 + q_2 \cdot y_2 $$

  • $q_1 + q_2 = 1$

이번엔 반비례가 적용되기 전 $x$축의 수식을 정리해 보자. 무게중심좌표를 $t_1, t_2$로 지정하고, $x_1,x_2$사이의 점 $x'$을 구하는 수식은 아래와 같다.

$$ x' = t_1\cdot x_1 + t_2 \cdot x_2 $$

 

두 값은 서로 반비례 관계이므로, $y$값을 $x$값으로 표현하면 아래와 같은 식이 성립한다.

$$ \frac{1}{x'} = q_1\cdot \frac{1}{x_1} + q_2 \cdot \frac{1}{x_2} $$

그렇다면 주어진 두 점 $y_1,y_2$의 값과 둘의 무게중심좌표를 사용해 $x'$값을 계산할 수 있다.

$$ x' = \frac{1}{(q_1\cdot \frac{1}{x_1}+q_2\cdot\frac{1}{x_2})} $$

양변에 분모를 곱하면 다음의 식이 성립하고,

양변의 덧셈항을 분리하면 다음의 관계를 얻을 수 있다.

$$ t_1 = \frac{x'}{x_1}q_1, \ \ \ t_2 = \frac{x'}{x_2}q_2 $$

 

앞선 예의 $y$축에서 무게중심좌표는 각각 0.25와 0.75였다. 이를 통해 $x$축에서의 무게중심좌표 0.5가 잘 계산되는지 확인해 보자.

$$ q_1 = \frac{1}{4}, \ \ q_2 = \frac{3}{4} $$

$$ t_1 = \frac{x'}{x_1} q_1 = \frac{4}{2} \cdot \frac{1}{4} = 0.5 \\ t_2 = \frac{x'}{x_2} q_2 = \frac{4}{6} \cdot \frac{3}{4} = 0.5 $$

위처럼 $x$축에서의 무게중심좌표 0.5가 잘 계산됨을 확인할 수 있다.

 

두 점에 조합에 대한 무게중심좌표를 확장해 삼각형을 구정하는 세 점의 조합에도 동일하게 적용할 수 있다.

 

위 식을 사용하여 NDC에서 구한 무게중심좌표를 투영 전 무게중심좌표로 변환해 보자. NDC로 변환할 때 나누는 값은 뷰 공간의 $z$값이므로, 위 식에서 $x$를 $-z$로 치환하면 최종 투영 보정 보간식을 얻을 수 있다.

[최종 투영 보정 보간식]

■ 깊이 버퍼

같은 거리에 있는 두 게임 오브젝트가 서로 겹쳐있다면, 물체 단위로 그리는 순서를 조절하는 것으로는 문제를 해결할 수 없다.

근본적인 해결 방식은 오브젝트 단위가 아닌, 삼각형의 픽셀 단위로 깊이를 비교하여 가까운 곳의 픽셀만 그리는 것이다.

  • 이를 구현하기 위해 화면의 픽셀마다 현재의 깊이 값을 보관해 주는 별도의 저장 공간이 필요한데, 이를 깊이 버퍼(Depth buffer)라고 한다.
  • 깊이 버퍼에 저장된 값을 비교하여 현재 깊이 값이 작은 경우에만 픽셀을 찍도록 로직을 구성하면, 그리지 않아도 되는 픽셀을 파악해 그리기를 건너뛸 수 있는데, 이 작업을 깊이 테스팅이라 한다.

 

 

 

728x90

'게임수학' 카테고리의 다른 글

[게임수학] 10-1. 원근 투영  (0) 2026.02.28
[게임수학] 9-3. 외적(3) - 삼중곱  (0) 2025.11.11
[게임수학] 9-2. 외적(2) - 카메라의 회전 행렬, 로드리게스 공식  (0) 2025.11.11
[게임수학] 9-1. 외적(Cross product)  (0) 2025.11.11
[게임수학] 8-2. 오일러 각의 단점(짐벌락, 회전 보간)  (0) 2025.10.14
'게임수학' 카테고리의 다른 글
  • [게임수학] 10-1. 원근 투영
  • [게임수학] 9-3. 외적(3) - 삼중곱
  • [게임수학] 9-2. 외적(2) - 카메라의 회전 행렬, 로드리게스 공식
  • [게임수학] 9-1. 외적(Cross product)
브라더스톤
브라더스톤
유티니, C#과 관련한 여러 정보를 끄적여둔 블로그입니다. Email : dkavmdk98@gmail.com
  • 브라더스톤
    젊은 프로그래머의 슬픔
    브라더스톤
  • 전체
    오늘
    어제
    • 개발 노트 (57)
      • Unity,C# (32)
        • Unity 정보 (9)
        • 알고리즘 (11)
        • 자료구조 (3)
        • 절차적생성(PCG) (9)
      • 게임수학 (16)
      • C++ (8)
        • 자료구조 (8)
      • 게임 (1)
        • 리치마작 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    pcg
    게임수학
    UI Toolkit
    외적
    자료구조
    정렬알고리즘
    unity
    C#
    c++
    원근투영행렬
    CustomWindow
    절차적지형생성
    이진공간분할
    PerlinNoise
    최단경로찾기
    BSP
    커스텀 윈도우
    스택
    절차적던전생성
    알고리즘
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.3
브라더스톤
[게임수학] 10-2. 깊이 값
상단으로

티스토리툴바