Make Unreal REAL.
article thumbnail
이득우의 게임 수학

 

다수의 게임 오브젝트를 그리는 경우, 카메라로부터 멀리 떨어진 게임 오브젝트를 먼저 그린 후 가까운 오브젝트를 그리도록 해야 원근감이 올바르게 표현횐다.

 

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

 

따라서 근본적인 해결 방법은 게임 오브젝트 단위가 아닌, 삼각형의 픽셀 단위로 깊이를 비교해 가까운 곳에 있는 픽셀만 그리는 것이다.

  • 이를 위해 화면의 픽셀마다 현재의 깊이 값을 보관해주는 별도의 저장 공간이 필요한데, 이를 깊이 버퍼 혹은 Z-버퍼(Z-buffer)라고 한다.

 

 

최종 픽셀을 찍는 과정에서 현재 깊이 값을 버퍼에 저장된 값과 비교해, 현재 깊이 값이 작은 경우에만 픽셀을 찍도록 구성한다.

 

그러면 물체에 가려져 그리지 않아도 되는 픽셀을 파악해 그리기를 건너뛸 수 있고, 이 작업을 깊이 테스팅(Depth testing)이라고 한다.

 

 

깊이 테스팅은 깊이의 대소만 비교하면 되기 때문에, [-1, 1] 범위로 매핑된 NDC의 z값을 그대로 사용해도 된다.

 

삼각형 폴리곤을 구성하는 세 점의 깊이 값 z₁, z₂, z₃로부터 계산된 각 픽셀의 무게 중심 좌표 q₁, q₂, q₃를 사용해 픽셀의 깊이 값 z'을 구하는 수식은 다음과 같다.

 

 

// 책의 예제인 CK소프트렌더러에서 삼각형을 그리는 함수
void SoftRenderer::DrawTriangle3D(std::vector<Vertex3D>& InVertices, const LinearColor& InColor, FillMode InFillMode)
{
    ...
    
    // 깊이 버퍼 테스팅
    if (toggleDepthTesting)
    {
        float newDepth = InVertices[0].Position.Z * oneMinusST + InVertices[1].Position.Z * s + InVertices[2].Position.Z * t;
        float prevDepth = r.GetDepthBufferValue(fragment);

        if (newDepth < prevDepth)
        {
            // 픽셀을 처리하기 전 깊이 값을 버퍼에 보관
            r.SetDepthBufferValue(fragment, newDepth);
        }
        else
        {
            // 이미 앞에 무언가 그려져 있으므로 픽셀 그리기 생략
            continue;
        }
    }
}

 

Z-버퍼 테스팅 전 (좌) / Z-버퍼 테스팅 후 (우)

'게임 수학 > 이득우의 게임 수학' 카테고리의 다른 글

직선의 방정식  (0) 2023.05.19
평면의 방정식  (0) 2023.05.18
원근 보정 매핑  (0) 2023.05.16
깊이(Depth)  (0) 2023.05.15
동차 좌표계  (0) 2023.05.14
profile

Make Unreal REAL.

@diesuki4

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그