3D 그래픽스의 컬링과 클립핑
들어가기 전에: 이 글을 쓰게 된 배경
TACampus 2주차 그래픽스(렌더링) 파이프라인과 셰이더 강의를 듣던 중, 클립핑 단원에서 '가드 밴드 클립핑'이라는 용어를 처음 접하게 되었습니다. 기존에는 일반적인 프러스텀 클립핑에 대해서만 알고 있었기 때문에, 이 새로운 개념이 매우 흥미로웠습니다.
실제 개발에서 클립핑을 직접 조정해본 적은 없지만, 이론적으로 어떻게 동작하는지 깊이 알고 싶었습니다. YouTube나 일반 검색으로는 자료가 많지 않아서, 주로 NVIDIA의 "Guard Band Clipping in Direct3D" 문서와 추가 리서치를 통해 내용을 정리하게 되었습니다.
왜 컬링과 클립핑이 중요한가?
현대 게임에서 플레이어가 보는 화면에는 수백만 개의 폴리곤이 존재할 수 있습니다. 하지만 실제로 화면에 그려져야 하는 것은 그 중 극히 일부분입니다. 나머지는 카메라 시야 밖에 있거나, 다른 오브젝트에 의해 가려져 있거나, 혹은 너무 멀리 있어서 보이지 않습니다. 이런 불필요한 렌더링 작업을 줄이는 것이 바로 컬링(Culling)과 클립핑(Clipping)의 역할입니다.
컬링(Culling)과 클립핑(Clipping)의 기본 개념
컬링(Culling)이란?
컬링은 보이지 않는 전체 오브젝트나 면을 렌더링 파이프라인에서 완전히 제거하는 과정입니다. 마치 무대에서 불필요한 소품을 치우는 것과 같습니다. 컬링된 오브젝트는 변환, 조명 계산, 래스터화 등의 모든 과정을 건너뛰게 됩니다.
컬링의 핵심은 바운딩 볼륨(Bounding Volume)을 사용하는 것입니다. 복잡한 메시의 수천 개 삼각형을 일일이 테스트하는 대신, 오브젝트를 감싸는 단순한 형태를 사용하여 빠른 판별을 수행합니다.
바운딩 볼륨의 종류
바운딩 스피어
가장 빠른 테스트
회전 불변
축 정렬 박스
계산이 간단
메모리 효율적
방향 박스
가장 정확한 근사
상대적으로 복잡
바운딩 스피어(Bounding Sphere): 단순함의 미학
바운딩 스피어는 오브젝트를 완전히 감싸는 가장 작은 구를 말합니다. 중심점 하나와 반지름 하나만으로 정의되기 때문에 메모리 사용량이 극도로 적고, 계산도 매우 빠릅니다. 가장 중요한 장점은 회전에 불변이라는 점입니다. 오브젝트가 어떻게 회전하든 바운딩 스피어는 변하지 않기 때문에, 회전하는 오브젝트들에 대해서는 매번 새로 계산할 필요가 없습니다.
바운딩 스피어의 회전 불변성
0° 회전
반지름: 60px
45° 회전
반지름: 60px
90° 회전
반지름: 60px
오브젝트가 어떻게 회전하든 바운딩 스피어(파란 원)의 크기는 항상 동일합니다. 이것이 바로 회전 불변성의 핵심입니다.
바운딩 스피어 판별 방법은 놀랍도록 간단합니다. 프러스텀 컬링에서 바운딩 스피어를 사용할 때는 각 프러스텀 평면에 대해 거리를 계산합니다. 구의 중심에서 평면까지의 거리가 반지름보다 크면 완전히 바깥쪽, 반지름보다 작으면 교차 또는 안쪽으로 판단합니다. 이 과정은 단순한 내적 연산과 거리 비교만으로 이루어지므로 매우 빠릅니다.
하지만 바운딩 스피어는 길쭉한 오브젝트에 대해서는 정확도가 떨어집니다. 위의 다이어그램에서 보듯이, 직사각형 주변에 상당한 빈 공간이 생깁니다. 예를 들어 긴 막대기 모양의 오브젝트를 구로 감싸면 실제 오브젝트보다 훨씬 큰 영역을 차지하게 되어, 실제로는 화면 밖에 있는데도 화면 안에 있다고 잘못 판단할 수 있습니다.
축 정렬 바운딩 박스(AABB): 균형잡힌 선택
AABB는 월드 좌표계의 축(X, Y, Z)에 평행한 면들로 구성된 직육면체입니다. 최소점(min)과 최대점(max) 두 개의 3차원 벡터만으로 정의되므로 메모리 효율적이면서도, 바운딩 스피어보다는 훨씬 정확한 근사가 가능합니다. 특히 건물이나 상자 같은 직육면체에 가까운 오브젝트들에 대해서는 매우 효과적입니다.
AABB의 축 정렬 제약과 회전 효과
0° 회전
AABB: 80×40px
정확도: 매우 높음
45° 회전
AABB: 90×70px
정확도: 중간
90° 회전
AABB: 40×80px
정확도: 다시 높음
AABB(빨간 점선)는 항상 축에 평행해야 하므로, 오브젝트 회전에 따라 크기가 변합니다. 45° 회전 시 가장 비효율적이 됩니다.
AABB와 프러스텀 평면 충돌 검사 최적화: Positive/Negative Vertex
3D 게임이나 애플리케이션에서 화면에 보이는 객체만 렌더링하여 성능을 높이는 프러스텀 컬링은 매우 중요합니다. 이때 객체를 둘러싼 AABB와 카메라의 시야 범위인 프러스텀의 충돌 여부를 판단하게 됩니다. 가장 단순하게 AABB의 8개 꼭짓점 모두가 프러스텀 내부에 있는지, 또는 하나라도 외부에 있는지를 검사하는 방법은 매우 비효율적입니다.
Positive/Negative Vertex 최적화의 필요성: 전통적인 방법으로 AABB의 8개 모든 꼭짓점을 프러스텀의 6개 평면에 대해 검사한다면 총 48번의 평면-점 거리 계산이 필요합니다. 이러한 비효율성을 개선하기 위해 Positive/Negative Vertex 최적화 기법을 사용하면 단 12번의 계산만으로 동일한 결과를 얻을 수 있습니다.
Positive/Negative Vertex의 정의: 프러스텀의 각 평면(왼쪽, 오른쪽, 위, 아래, 가까운, 먼 평면)과 AABB의 충돌을 검사할 때, 평면의 법선(normal) 방향을 기준으로 AABB의 두 특정 꼭짓점만 사용하여 판단하는 방식입니다.
• Positive Vertex (가장 먼 점): 특정 평면의 법선 방향으로 AABB에서 가장 멀리 떨어진 꼭짓점입니다.
• Negative Vertex (가장 가까운 점): 특정 평면의 법선 방향으로 AABB에서 가장 가까이 있는 꼭짓점입니다.
최적화 원리와 판별 과정: 각 프러스텀 평면에 대해 다음 규칙을 적용합니다:
1. AABB가 평면 바깥에 완전히 존재하는지 확인:
평면의 법선 방향과 AABB의 Negative Vertex를 내적하여 나온 값이 평면의 거리 값보다 크면, AABB는 해당 평면 바깥에 완전히 존재합니다. 이 경우 더 이상 검사할 필요 없이 해당 객체는 렌더링 대상에서 제외됩니다.
예시: 프러스텀의 왼쪽 평면(법선 벡터가 오른쪽을 향함)을 검사한다고 가정해봅시다. AABB의 Negative Vertex(가장 왼쪽 아래 뒤에 있는 점)가 이 평면보다 더 오른쪽에 있다면, AABB는 완전히 왼쪽 평면 바깥에 있다는 의미입니다.
2. AABB가 평면 내부에 완전히 존재하는지 확인:
평면의 법선 방향과 AABB의 Positive Vertex를 내적하여 나온 값이 평면의 거리 값보다 작으면, AABB는 해당 평면 내부에 완전히 존재합니다.
예시: 왼쪽 평면의 경우, AABB의 Positive Vertex(가장 오른쪽 위 앞에 있는 점)가 평면보다 더 왼쪽에 있다면, AABB는 완전히 왼쪽 평면 내부에 있다는 의미입니다.
꼭짓점 선택 공식: 평면의 법선 벡터 (nx, ny, nz)가 주어졌을 때, AABB의 최소값(min.x, min.y, min.z)과 최대값(max.x, max.y, max.z)을 사용하여 다음과 같이 계산됩니다:
• Positive Vertex: (nx>0 ? max.x : min.x, ny>0 ? max.y : min.y, nz>0 ? max.z : min.z)
• Negative Vertex: (nx>0 ? min.x : max.x, ny>0 ? min.y : max.y, nz>0 ? min.z : max.z)
성능 향상 효과: 이러한 방식으로 각 프러스텀 평면에 대해 단 두 개의 꼭짓점만 테스트하여 AABB가 평면에 대해 완전히 밖에 있는지, 완전히 안에 있는지, 아니면 교차하는지를 판단할 수 있습니다. 이를 통해 8개의 꼭짓점을 모두 검사하는 것보다 약 75% 더 효율적으로 프러스텀 컬링을 수행할 수 있으며, 이는 3D 그래픽스 엔진에서 성능 향상을 위해 널리 사용되는 핵심 기법 중 하나입니다.
AABB의 가장 큰 제약은 회전에 대한 처리입니다. 위의 다이어그램에서 명확히 보듯이, 오브젝트가 회전하면 AABB는 더 커져야 하므로, 회전하는 오브젝트에 대해서는 정확도가 크게 떨어집니다. 마치 대각선으로 놓인 긴 막대기를 축에 평행한 상자로 감싸려면 훨씬 큰 상자가 필요한 것과 같은 원리입니다.
방향 바운딩 박스(OBB): 정확성의 극대화
OBB는 임의의 방향을 가질 수 있는 직육면체입니다. 오브젝트의 실제 방향에 맞춰 박스를 정렬할 수 있기 때문에, 세 가지 바운딩 볼륨 중에서 가장 정확한 근사가 가능합니다. 중심점, 세 개의 축 방향, 그리고 각 축에 대한 반폭(half-width)으로 정의됩니다. 이는 수학적으로 더 복잡하지만, 그만큼 정밀한 제어가 가능합니다.
OBB의 적응적 정렬과 정확성
0° 회전
OBB: 80×40px
정확도: 완벽
45° 회전
OBB: 80×40px
정확도: 완벽
90° 회전
OBB: 80×40px
정확도: 완벽
OBB(보라 점선)는 오브젝트와 함께 회전하므로 항상 완벽하게 일치합니다. 하지만 계산 복잡도가 가장 높습니다.
OBB 판별 방법은 가장 정교하지만 복잡합니다. 분리축 정리(Separating Axis Theorem)를 사용하여, 프러스텀 평면의 법선을 분리축으로 하여 OBB를 투영한 후 거리를 계산합니다. 이 과정에서 OBB의 세 축과 프러스텀 평면 법선의 내적을 계산하여 투영된 반지름을 구해야 합니다. 수학적으로 표현하면, 투영된 반지름은 각 축 방향의 반폭과 해당 축이 평면 법선과 이루는 각도의 코사인 값을 곱한 것들의 절댓값 합입니다.
OBB는 가장 정확하지만 계산 비용이 가장 높습니다. 메모리 사용량도 많고, 특히 많은 수의 오브젝트를 빠르게 처리해야 하는 상황에서는 성능 부담이 될 수 있습니다. 하지만 위의 다이어그램에서 보듯이, 회전에 관계없이 항상 완벽한 정확도를 유지한다는 것은 큰 장점입니다.
CPU 컬링 vs GPU 컬링: 아키텍처의 차이가 만드는 성능 특성
CPU 컬링은 주로 오브젝트 단위로 수행됩니다. CPU의 핵심 강점은 브랜칭(조건 분기) 처리에 있습니다. 브랜칭이란 "만약 이 조건이 참이면 A를 실행하고, 거짓이면 B를 실행한다"는 식의 조건부 실행을 의미합니다. CPU는 복잡한 분기 예측기(Branch Predictor)와 파이프라인을 통해 이러한 조건부 로직을 매우 효율적으로 처리할 수 있습니다.
예를 들어, "이 오브젝트가 프러스텀 안에 있는가?"라는 질문에 대해 CPU는 각 오브젝트마다 다른 결과를 가질 수 있고, 그에 따라 완전히 다른 코드 경로를 실행할 수 있습니다. 어떤 오브젝트는 즉시 렌더링하고, 어떤 것은 추가 테스트를 거치고, 또 다른 것은 완전히 건너뛸 수 있습니다. 이러한 복잡한 의사결정 과정이 CPU 컬링의 핵심입니다.
GPU 컬링은 완전히 다른 철학을 가지고 있습니다. GPU는 수천 개의 작은 코어들이 동일한 명령을 병렬로 실행하는 SIMD(Single Instruction, Multiple Data) 아키텍처를 기반으로 합니다. 이는 마치 거대한 공장에서 모든 작업자가 동시에 같은 작업을 수행하는 것과 같습니다.
GPU에서 브랜칭이 문제가 되는 이유는 "워프(Warp)" 또는 "웨이브프런트(Wavefront)"라는 실행 단위 때문입니다. 워프란 GPU에서 동시에 실행되는 스레드들의 그룹을 의미합니다. NVIDIA GPU에서는 보통 32개의 스레드가 하나의 워프를 구성하고, AMD GPU에서는 64개의 스레드가 하나의 웨이브프런트를 구성합니다. 이들은 모두 동일한 명령어를 실행해야 하는 SIMT(Single Instruction, Multiple Thread) 방식으로 동작합니다.
문제는 이 그룹 내에서 일부 스레드는 조건문의 참 분기를, 다른 스레드는 거짓 분기를 실행해야 할 때 발생합니다. 예를 들어, 32개 스레드 중 16개는 "오브젝트를 렌더링하라"는 코드를, 나머지 16개는 "오브젝트를 컬링하라"는 코드를 실행해야 한다면, GPU는 먼저 16개 스레드만 활성화하여 첫 번째 분기를 실행하고, 그 다음에 나머지 16개 스레드를 활성화하여 두 번째 분기를 실행해야 합니다. 이를 "워프 분기(Warp Divergence)"라고 하며, 병렬성이 크게 저하되는 원인입니다.
GPU의 조건부 실행 최적화 기법들: 하지만 최근의 GPU는 이러한 제약을 우회하는 고급 기법들을 사용합니다. 마스킹(Masking) 기법은 조건문 대신 비트 마스크를 사용하여 특정 스레드들만 연산 결과를 실제로 적용하는 방법입니다. 예를 들어, 모든 스레드가 동일한 컬링 계산을 수행하지만, 마스크를 통해 일부 스레드의 결과만 유효하다고 표시하는 식입니다.
프레디케이션(Predication)은 더욱 정교한 기법으로, 조건문을 완전히 제거하고 대신 모든 경로를 실행한 후 조건에 따라 결과를 선택하는 방식입니다. 이는 분기가 일어나지 않으므로 워프 내의 모든 스레드가 동일한 속도로 실행될 수 있습니다. 현대 GPU 아키텍처에서는 하드웨어 레벨에서 이런 기법들을 지원하여 개발자가 의식하지 않아도 자동으로 최적화가 적용됩니다.
클립핑(Clipping)이란?
클립핑은 부분적으로 보이는 프리미티브(삼각형, 선 등)를 뷰 볼륨에 맞게 잘라내는 과정입니다. 예를 들어, 삼각형의 일부가 화면 밖으로 나가있다면, 화면 안쪽 부분만 남기고 나머지는 제거합니다. 이 과정에서 새로운 정점들이 생성될 수 있습니다.
클립핑은 주로 GPU에서 수행되며, 정점 셰이더 이후 래스터화 이전 단계에서 일어납니다. 개별 프리미티브 단위로 처리되기 때문에 컬링보다 더 정밀하지만 비용이 높습니다.
구분 | 컬링(Culling) | 클립핑(Clipping) |
---|---|---|
정의 | 보이지 않는 전체 오브젝트/면을 제거 | 부분적으로 보이는 프리미티브를 자르기 |
처리 단위 | 오브젝트, 면 단위 | 개별 프리미티브(삼각형, 선) 단위 |
처리 위치 | 주로 CPU (애플리케이션 레벨) | 주로 GPU (그래픽스 파이프라인) |
지오메트리 변경 | 변경하지 않음 (단순 제거) | 새로운 정점과 프리미티브 생성 가능 |
성능 특성 | 빠른 판별, 큰 성능 향상 | 정밀한 처리, 상대적으로 비싼 비용 |
다양한 컬링 기법들
뷰 프러스텀 컬링(View Frustum Culling)
뷰 프러스텀 컬링은 카메라의 시야 절두체(Frustum) 밖에 있는 오브젝트들을 제거하는 기법입니다. 프러스텀은 근거리 평면(Near Plane)과 원거리 평면(Far Plane), 그리고 4개의 측면 평면으로 구성된 6면체입니다.
뷰 프러스텀 구조
백페이스 컬링(Backface Culling): 보이지 않는 면을 걸러내는 지능적 최적화
백페이스 컬링은 카메라를 향하지 않는 면들을 제거하는 기법입니다. 이는 3D 그래픽스에서 가장 기본적이면서도 효과적인 최적화 중 하나로, 닫힌 메시(Closed Mesh)에서는 뒷면이 항상 앞면에 의해 가려진다는 기하학적 원리를 활용합니다.
백페이스 컬링의 원리: 와인딩 순서와 법선 벡터
앞면 (Front Face)
반시계 방향 와인딩
법선이 카메라를 향함
렌더링됨
뒷면 (Back Face)
시계 방향 와인딩
법선이 카메라 반대를 향함
컬링됨
정점의 와인딩 순서에 따라 면의 방향이 결정되며, 이를 통해 앞면과 뒷면을 구분합니다
와인딩 순서(Winding Order)의 중요성: 삼각형의 정점들이 화면에서 어떤 순서로 배열되는지에 따라 그 면이 앞면인지 뒷면인지 결정됩니다. 일반적으로 반시계 방향(Counter-Clockwise)으로 배열된 정점들은 앞면을, 시계 방향(Clockwise)으로 배열된 정점들은 뒷면을 나타냅니다. 이는 오른손 법칙에 따른 것으로, 손가락을 정점 순서대로 구부렸을 때 엄지가 가리키는 방향이 면의 법선 방향이 됩니다.
내적 계산을 통한 판별: 더 수학적인 접근 방법으로는 면의 법선 벡터와 카메라로 향하는 벡터의 내적을 계산하는 방법이 있습니다. 내적 값이 양수이면 두 벡터가 같은 방향을 향하므로 앞면이고, 음수이면 반대 방향이므로 뒷면입니다. 이 방법은 특히 변형된 지오메트리나 복잡한 변환이 적용된 경우에도 정확하게 작동합니다.
3D 모델에서의 백페이스 컬링 효과
백페이스 컬링 비활성화
모든 면을 렌더링
불필요한 GPU 연산
성능 저하
백페이스 컬링 활성화
보이는 면만 렌더링
GPU 연산 절약
성능 향상
백페이스 컬링의 성능 특성 분석
⚡ 성능 향상
일반적으로 50% 정도의 삼각형을 제거할 수 있습니다. 닫힌 구 모델의 경우, 어떤 각도에서 보더라도 절반 이상의 면은 항상 뒷면이 되므로 상당한 성능 향상을 기대할 수 있습니다.
💾 처리 비용
단순한 내적 계산이나 와인딩 순서 확인만으로 처리되므로 오버헤드가 거의 없습니다. 하드웨어 레벨에서 지원되어 추가적인 CPU 부담도 없습니다.
⚠️ 제약사항
양면이 모두 보여야 하는 오브젝트(나무 잎사귀, 천, 얇은 벽 등)에는 사용할 수 없습니다. 이런 경우에는 백페이스 컬링을 비활성화하거나 양면 렌더링을 설정해야 합니다.
하드웨어 수준의 구현: 현대 GPU에서 백페이스 컬링은 래스터화 단계에서 하드웨어적으로 수행됩니다. 이는 정점 셰이더가 완료된 후 프리미티브 어셈블리 단계에서 일어나므로, 개발자가 별도의 코드를 작성할 필요가 없습니다. 단순히 그래픽스 API에서 백페이스 컬링을 활성화하기만 하면 됩니다.
오클루전 컬링(Occlusion Culling): 가려진 오브젝트를 찾아내는 고급 기법
오클루전 컬링은 다른 오브젝트에 의해 완전히 가려진 오브젝트들을 제거하는 기법입니다. 이는 가장 복잡하지만 동시에 가장 큰 성능 향상을 가져올 수 있는 컬링 기법으로, 특히 복잡한 실내 환경이나 도시 환경에서 그 위력을 발휘합니다.
오클루전 컬링의 시각적 이해
큰 벽(Occluder) 뒤에 가려진 오브젝트들은 실제로 보이지 않으므로 렌더링할 필요가 없습니다
오클루전 컬링의 복잡성: 오클루전 컬링이 어려운 이유는 "무엇이 무엇을 가리고 있는가?"를 정확히 판단하기 어렵기 때문입니다. 프러스텀 컬링처럼 단순한 공간적 관계가 아니라, 깊이와 겹침이라는 3차원적 관계를 고려해야 합니다. 또한 카메라 위치가 조금만 변해도 가려짐 관계가 완전히 바뀔 수 있어서 동적인 환경에서는 매우 복잡한 계산이 필요합니다.
다양한 오클루전 컬링 기법들
🔧 하드웨어 오클루전 쿼리
GPU가 실제로 그려진 픽셀 수를 측정하여 오브젝트가 보이는지 판단하는 방법입니다. Unity와 Unreal Engine의 동적 오클루전 컬링이 이 방식을 사용합니다.
📊 사전 계산된 가시성 집합 (PVS)
레벨을 여러 셀로 나누고 각 셀에서 보이는 오브젝트들을 미리 계산해두는 방법입니다. 모바일이나 저사양 하드웨어에 적합합니다.
🚪 포털 렌더링
실내 환경에서 방과 복도를 포털로 연결하여 현재 방에서 보이는 다른 방들만 렌더링하는 방법입니다. Doom이나 Quake 같은 초기 FPS 게임에서 널리 사용되었습니다.
하드웨어 오클루전 쿼리의 세부 동작: 이 방법은 GPU의 깊이 테스트 기능을 활용합니다. 먼저 오브젝트의 바운딩 박스를 단순한 형태로 렌더링하되, 색상 버퍼에는 쓰지 않고 깊이 테스트만 수행합니다. 그 결과 실제로 화면에 그려진 픽셀의 개수를 GPU가 카운트해줍니다. 만약 카운트가 0이라면 해당 오브젝트는 완전히 가려져 있다는 뜻이므로 컬링할 수 있습니다.
사전 계산된 가시성 집합(PVS)의 장단점: PVS는 레벨 디자인 단계에서 모든 가시성 관계를 미리 계산해두므로 런타임 성능이 매우 뛰어납니다. 하지만 동적 오브젝트의 변화를 반영하기 어렵고, 레벨이 변경될 때마다 다시 계산해야 한다는 단점이 있습니다. 특히 파괴 가능한 환경이나 실시간으로 변하는 구조물이 있는 게임에서는 적용하기 어렵습니다.
포털 렌더링의 현대적 응용: 포털 렌더링은 고전적인 기법이지만 현재도 실내 환경에서는 매우 효과적입니다. 현대 게임에서는 더 정교한 형태로 발전하여 "가시성 그래프" 개념으로 구현되기도 합니다. 각 방이나 구역을 노드로, 연결 통로를 엣지로 하는 그래프를 만들어서 현재 위치에서 도달 가능한 구역들만 렌더링하는 방식입니다.
다양한 클립핑 기법들
뷰 프러스텀 클립핑
뷰 프러스텀 클립핑은 카메라의 시야 절두체를 벗어나는 프리미티브들을 잘라내는 과정입니다. 이는 정점 변환 후 클립 공간에서 수행되며, NDC(Normalized Device Coordinates) 범위인 [-1, 1]을 벗어나는 부분들을 제거합니다.
Sutherland-Hodgman 알고리즘이 대표적인 클립핑 알고리즘으로, 6개의 프러스텀 평면을 순차적으로 적용하여 삼각형을 자릅니다. 이 과정에서 삼각형이 여러 개로 분할될 수 있으며, 모든 정점 속성(UV 좌표, 색상, 법선 등)을 적절히 보간해야 합니다.
Sutherland-Hodgman 클립핑 알고리즘의 단계별 동작
Sutherland-Hodgman 알고리즘은 각 클립 평면을 순차적으로 적용하여 폴리곤을 점진적으로 잘라나갑니다
Sutherland-Hodgman 알고리즘의 세부 동작: 이 알고리즘은 "inside-outside" 테스트를 기반으로 합니다. 폴리곤의 각 모서리에 대해 시작점과 끝점이 클립 평면의 안쪽에 있는지 바깥쪽에 있는지 판별합니다. 네 가지 경우가 있습니다: (1) 양쪽 모두 안쪽 - 끝점 추가, (2) 시작점은 안쪽, 끝점은 바깥쪽 - 교점 추가, (3) 시작점은 바깥쪽, 끝점은 안쪽 - 교점과 끝점 추가, (4) 양쪽 모두 바깥쪽 - 아무것도 추가하지 않음. 이 과정을 6개의 프러스텀 평면에 대해 순차적으로 반복하면 최종적으로 뷰 볼륨 내부의 폴리곤만 남게 됩니다.
근거리/원거리 평면 클립핑: 뷰 프러스텀의 깊이 경계 처리
근거리와 원거리 평면 클립핑은 3D 렌더링에서 핵심적인 역할을 하는 기법으로, 카메라로부터 너무 가깝거나 너무 먼 지오메트리를 제거하는 과정입니다. 이는 단순한 최적화를 넘어서 수학적 안정성과 정확한 깊이 표현을 위해 반드시 필요한 과정입니다.
근거리/원거리 평면 클립핑의 3차원 시각화
근거리 평면 앞과 원거리 평면 뒤의 지오메트리는 클립핑으로 제거됩니다
근거리 평면 클립핑의 수학적 필요성: 근거리 평면 클립핑이 필수적인 이유는 투영 변환의 수학적 특성 때문입니다. 3D 공간의 점을 2D 화면으로 투영할 때, 카메라로부터의 거리 z값으로 나누는 과정이 포함됩니다. 만약 z값이 0에 가까워지면 나눗셈 결과가 무한대로 발산하게 되어 수치적 불안정성을 야기합니다. 또한 카메라 바로 뒤에 있는 오브젝트들은 화면에서 뒤집혀 보이는 현상이 발생하므로, 이를 방지하기 위해서라도 근거리 클립핑이 필요합니다.
근거리 평면의 설정 원칙: 근거리 평면은 너무 가깝게 설정하면 z-파이팅(Z-fighting) 문제를 일으킬 수 있고, 너무 멀리 설정하면 가까운 오브젝트들이 잘려 보이는 문제가 발생합니다. 일반적으로 0.1에서 1.0 유닛 사이에서 설정하며, 게임의 스케일과 필요한 정밀도에 따라 조정합니다. FPS 게임처럼 가까운 오브젝트가 중요한 경우에는 0.01 정도로 매우 가깝게 설정하기도 합니다.
깊이 버퍼 정밀도와 클립핑 평면의 관계
✅ 적절한 클립핑 거리
❌ 부적절한 클립핑 거리
원거리 평면 클립핑의 역할: 원거리 평면은 렌더링해야 할 세계의 경계를 정의합니다. 이는 단순히 멀리 있는 오브젝트를 제거하는 것을 넘어서 깊이 버퍼의 정밀도 분배에도 중요한 영향을 미칩니다. 깊이 버퍼의 정밀도는 비선형적으로 분포되어 있어서, 근거리와 원거리 평면의 비율이 클수록 먼 거리에서의 정밀도가 급격히 떨어집니다. 따라서 원거리 평면을 적절히 설정하는 것은 z-파이팅 방지에 매우 중요합니다.
z-파이팅(Z-fighting): 깊이 정밀도 부족으로 인한 시각적 문제
z-파이팅은 두 개 이상의 폴리곤이 거의 같은 깊이에 위치할 때 발생하는 렌더링 오류입니다. 이는 깊이 버퍼의 정밀도 한계로 인해 GPU가 어떤 폴리곤이 앞에 있는지 정확히 판단하지 못해서 발생합니다. 그 결과 두 폴리곤이 번갈아가며 깜빡거리거나 얼룩덜룩하게 보이는 현상이 나타납니다.
z-파이팅 현상의 원리와 예방
❌ z-파이팅 발생
두 폴리곤의 깊이 차이가 너무 작아서 깊이 버퍼로 구분할 수 없어 깜빡거림이 발생합니다.
✅ z-파이팅 해결
충분한 깊이 차이를 두거나 적절한 클립핑 평면 설정으로 z-파이팅을 방지할 수 있습니다.
z-파이팅의 수학적 원인: 1/z 곡선의 비선형성: 깊이 버퍼는 대부분 24비트로 구성되어 있어 약 1600만 개의 서로 다른 깊이 값을 표현할 수 있습니다. 하지만 이 값들이 선형적으로 분포되어 있지 않고 1/z 곡선을 따라 분포됩니다. 1/z 곡선이란? 3D 공간의 z값(실제 거리)을 깊이 버퍼 값으로 변환할 때 사용되는 수학적 관계입니다. 원근 투영에서 화면의 한 점에 대응하는 3D 공간의 점들은 z값에 반비례하는 관계를 가집니다. 즉, 거리가 2배가 되면 깊이 버퍼에서의 정밀도는 1/2로 줄어들고, 거리가 10배가 되면 정밀도는 1/10로 줄어듭니다. 이는 가까운 거리에서는 매우 높은 정밀도를 제공하지만, 먼 거리에서는 정밀도가 급격히 떨어진다는 의미입니다.
1/z 곡선과 깊이 버퍼 정밀도 분포
1/z 곡선으로 인해 깊이 버퍼의 정밀도가 근거리에 집중되어 원거리에서 z-파이팅이 발생하기 쉽습니다
예를 들어 근거리 평면이 0.1이고 원거리 평면이 1000인 경우, 전체 정밀도의 약 50%가 거리 0.1에서 1.0 사이에 집중됩니다. 이는 원근 투영에서 1/z 분포를 사용하기 때문입니다.
z-파이팅 방지 전략: 첫 번째는 근거리와 원거리 평면의 비율을 적절히 설정하는 것입니다. 비율이 클수록 원거리에서의 정밀도가 떨어지므로, 꼭 필요한 범위만 설정해야 합니다. 두 번째는 폴리곤 오프셋(Polygon Offset) 기법을 사용하는 것입니다. 이는 렌더링 시 특정 폴리곤의 깊이 값을 약간 조정하여 겹침을 방지하는 방법입니다. 세 번째는 데칼이나 오버레이 같은 경우 스텐실 버퍼를 활용하여 아예 다른 렌더링 패스로 처리하는 것입니다.
클립핑 과정에서의 정점 속성 보간
클립핑 시 새로 생성되는 정점들은 원본 정점들의 모든 속성을 적절히 보간하여 계산됩니다
클립핑 시 정점 속성 보간의 복잡성: 클립핑 과정에서 새로운 정점이 생성될 때, 단순히 위치만 계산하는 것이 아니라 모든 정점 속성들을 적절히 보간해야 합니다. 이는 선형 보간으로 이루어지는데, 예를 들어 두 정점 사이의 중점에서 클립핑이 일어난다면 텍스처 좌표도 정확히 중간값을 가져야 하고, 색상 정보도 두 정점의 평균값을 가져야 합니다. 이 과정이 정확하지 않으면 클립핑된 경계에서 텍스처가 왜곡되거나 색상이 부자연스럽게 변하는 현상이 발생할 수 있습니다.
무한 원거리 평면 기법과 역방향 깊이 버퍼: 일부 고급 렌더링 시스템에서는 원거리 평면을 무한대로 설정하는 기법을 사용합니다. 이는 하늘이나 매우 먼 배경을 자연스럽게 렌더링하는 데 유용하지만, 깊이 버퍼 정밀도가 더욱 비선형적으로 분포하게 되므로 z-파이팅에 더 취약해집니다. 이런 경우에는 대신 역방향 깊이 버퍼(Reversed Depth Buffer) 기법을 사용하여 정밀도 분포를 개선하기도 합니다.
역방향 깊이 버퍼(Reversed Depth Buffer)의 정밀도 개선 효과
역방향 깊이 버퍼는 부동소수점의 특성을 활용하여 근거리에서 더 높은 정밀도를 제공합니다
역방향 깊이 버퍼의 수학적 원리: IEEE 754 부동소수점 표준에서는 1.0에 가까운 값들이 0.0에 가까운 값들보다 더 조밀하게 분포되어 있습니다. 전통적인 깊이 버퍼에서는 0.0을 근거리로, 1.0을 원거리로 사용하므로 원거리에서 더 높은 정밀도를 가지게 됩니다. 하지만 실제로는 근거리에서 더 높은 정밀도가 필요하므로, 역방향 깊이 버퍼는 이를 뒤집어서 1.0을 근거리로, 0.0을 원거리로 사용합니다. 이렇게 하면 플레이어가 주로 상호작용하는 가까운 오브젝트들에서 z-파이팅이 크게 줄어들고, 무한 원거리 평면도 안정적으로 사용할 수 있습니다.
가드 밴드 클립핑: 혁신적인 최적화 기법
가드 밴드 클립핑의 정의
가드 밴드 클립핑은 뷰포트보다 훨씬 큰 "가드 밴드" 영역을 설정하고, 이 영역 내의 프리미티브들은 클립핑 없이 GPU로 전달하는 최적화 기법입니다. 전통적인 클립핑이 뷰포트 경계에서 즉시 프리미티브를 자르는 반면, 가드 밴드 클립핑은 훨씬 더 큰 영역까지 허용합니다.
가드 밴드 클립핑 개념도: 뷰포트와 가드 밴드의 관계
가드 밴드 내부
뷰포트 넘지만 가드 밴드 내부
클립 공간 범위 초과
가드 밴드 밖, 뷰포트 무관
NVIDIA 문서의 가드 밴드 클립핑 개념을 현대 GPU 아키텍처 관점에서 재해석한 다이어그램입니다. 각 삼각형의 위치에 따른 처리 방식을 보여줍니다.
예를 들어, NVIDIA의 RIVA TNT 시리즈는 실제 화면 해상도와 관계없이 -2048부터 +2047까지의 2D 화면 좌표를 지원했고, GeForce 256은 무려 ±100,000,000까지의 거대한 가드 밴드를 지원했습니다. 현대 GPU에서는 클립 공간의 w 좌표를 기준으로 한 더욱 정교한 가드 밴드 시스템을 사용하여, 하드웨어가 처리할 수 있는 범위를 동적으로 확장합니다.
가드 밴드 클립핑의 작동 원리와 성능 이점
전통적인 클립핑의 문제점을 먼저 이해해봅시다. 뷰포트 경계를 넘나드는 삼각형을 클립핑하려면 다음과 같은 비싼 작업들이 필요합니다:
• 경계면과의 교점 계산을 위한 복잡한 수학 연산
• 새로운 정점에서의 모든 속성(좌표, UV, 색상, 법선 등) 보간
• 삼각형 스트립과 팬의 분해
• 정점 캐시 일관성 저하
가드 밴드 클립핑의 해결책: 가드 밴드 영역 내에 있는 대부분의 삼각형들은 클립핑 없이 그대로 GPU로 전달됩니다. GPU의 래스터라이저가 나중에 뷰포트 밖의 픽셀들을 간단히 시저링(Scissoring)으로 제거하면 됩니다. 이는 CPU에서의 복잡한 클립핑 계산보다 훨씬 빠릅니다.
가드 밴드를 활용한 컬링 및 클립핑 전략
가드 밴드 클립핑을 최대한 활용하려면 2단계 접근법을 사용합니다:
1단계: 확장된 프러스텀 컬링
기존의 뷰 프러스텀 외에 가드 밴드까지 포함하는 "가드 밴드 프러스텀"을 생성합니다. 오브젝트의 바운딩 볼륨이 이 확장된 프러스텀 내에 완전히 들어있다면, 해당 오브젝트의 모든 삼각형을 클립핑 없이 렌더링할 수 있습니다.
이 방법은 마치 더 큰 안전지대를 만드는 것과 같습니다. 원래 화면 영역보다 훨씬 큰 영역을 설정하여, 대부분의 오브젝트가 이 "안전지대" 안에 들어가도록 합니다. 그러면 복잡한 클립핑 계산 없이도 대부분의 경우를 처리할 수 있습니다.
2단계: 삼각형별 전략
개별 삼각형 수준에서도 가드 밴드를 고려한 처리를 합니다:
• 삼각형 A (가드 밴드 내부): 즉시 수락 또는 간단한 거부
• 삼각형 B (뷰포트 넘지만 가드 밴드 내부): GPU 시저링으로 처리
• 삼각형 C (클립 공간 범위 초과): 하드웨어가 처리할 수 있는 클립 공간(w 좌표 범위)을 벗어나는 경우에만 소프트웨어 클립핑 필요
• 삼각형 D (가드 밴드 밖, 뷰포트와 교차 없음): 즉시 거부
현대 GPU에서의 가드 밴드 처리: 현대 GPU는 클립 공간 [-w, w]에서 클립을 수행하며, 가드 밴드는 이 클립 공간의 범위를 확장하여 하드웨어가 더 넓은 범위의 프리미티브를 자동으로 처리할 수 있도록 돕습니다. 가드 밴드 영역 내의 프리미티브들은 하드웨어 클립핑에 의해 처리되며, 오직 w 좌표의 수배를 초과하는 극단적인 경우에만 소프트웨어 클립핑이 필요합니다. 실제로는 대부분의 경우 개발자가 오브젝트 컬링 단계에서 미리 걸러내므로, 소프트웨어 클립핑까지 가는 경우는 매우 드뭅니다.
실제 성능 향상 사례: NVIDIA의 연구에 따르면, 가드 밴드 클립핑을 사용할 때 전체 클립핑 연산의 약 80-90%를 제거할 수 있었습니다. 특히 복잡한 3D 씬에서 많은 삼각형들이 화면 경계를 살짝 벗어나는 경우가 많은데, 이런 상황에서 가드 밴드 클립핑의 효과가 극대화됩니다. 현대 GPU에서는 클립 공간의 확장된 범위와 하드웨어 클립핑의 발전으로 이러한 효과가 더욱 향상되었으며, 게임에서는 카메라 움직임이나 오브젝트 애니메이션으로 인해 지오메트리가 지속적으로 화면 경계를 넘나드는 상황에서 가드 밴드가 안정적인 성능을 제공합니다.