3 분 소요

절두체 컬링(Frustum Culling)

카메라의 시야 볼륨(Frustum) 밖 오브젝트를 드로우 제출(렌더링) 이전에 제외하여, 불필요한 렌더링 비용을 줄이는 최적화 기법

Image

  • 정의
    • 카메라의 시야를 나타내는 절두체(Frustum) 내부에 있는 오브젝트만 렌더링
    • 절두체 밖 오브젝트는 렌더링 단계(드로우콜 제출) 이전에 제외
      • 렌더링 파이프라인 단게에서 수행되는 다른 컬링 개념과는 다소 다른 편
        • 클리핑(Cliping) : 제출된 도형이 화면 밖으로 나갔을때, 화면 경계에 맞게 ‘잘라냄’(RS)
        • 오클루젼(Occlusion)
          절두체 내부에 존재하여도 ‘다른 물체’에 가려져 카메라에 안보이는 오브젝트를 제외
          -> 다만 이는 실제로 모든 물체를 ‘그려봐야’ 알기에 매우 무거움!
          (OM)
  • 왜 필요한가?
    • 화면에 보이지 않는 오브젝트를 렌더 파이프라인에 태우면 비용이 발생함
      • CPU: DrawCall 기록/상태 변경/커맨드 버퍼 생성 등 제출 오버헤드
      • GPU: Vertex/Primitive 처리, Rasterization, Pixel shading, 메모리 대역폭 사용
    • 따라서 “가벼운 컬링 계산”으로 “무거운 렌더링 작업”을 처리!

절두체(Frustum)란?

  • 형태
    • 원근(Perspective) 투영: 가까운 면(Near)이 작고 먼 면(Far)이 큰 절두체(Truncated pyramid)
    • 직교(Orthographic) 투영: 상자(Box) 형태
  • 구성
    • 절두체는 다음 6개의 평면으로 정의
      • Left / Right / Top / Bottom / Near / Far

절두체를 구하는 방법

1) 기하학적 구성: 8개 코너 → 6개 평면

  • 입력
    • 카메라 위치 C
    • 카메라 축 R( right ), U( up ), F( forward )
    • 투영 파라미터 FOV, Aspect, Near, Far
  • 아이디어
    • Near/Far 평면의 중심을 구한 뒤,
    • R, U 방향으로 너비/높이만큼 이동해 Near 4개 + Far 4개 = 8개 코너를 만듦

Image

  • 평면의 법선(외적)
    • 코너 3점 A, B, C가 있을 때 평면 법선은 다음처럼 표현 가능
      • n = normalize((B - A) × (C - A))
    • 법선 방향은 절두체 내부를 향하도록 점 순서(와인딩) 또는 부호를 맞춤

2) 행렬 기반: View-Projection(VP)에서 6개 평면 추출

  • View 행렬
    • 월드 좌표를 카메라 좌표로 변환
    • “카메라를 움직이는 대신, 월드를 카메라 반대로 이동”시키는 역변환 개념
  • Projection 행렬
    • FOV / Aspect / Near / Far를 이용해 원근(또는 직교) 투영을 수행
    • 클립 공간(Clip Space)으로 사상하기 위한 변환
  • ViewProjection
    • VP = Projection * View
    • 클립 공간 경계 조건(예: -w ≤ x ≤ w, -w ≤ y ≤ w, z 범위)을
      clip = VP * world에 대입하면 월드 공간의 6개 평면(Frustum planes) 을 얻을 수 있음

평면 방정식과 내적 판정

  • 평면 방정식
    • 평면은 보통 아래 형태로 표현
      • n · p + d >= 0 → 내부(inside)
        • n: 평면의 법선(normal)
        • d: 상수항
        • p: 검사할 점(위치)

Image

  • 왜 내적으로 판정할 수 있나?
    • n · p + d의 결과(+/0/-)가 점 p가 평면 기준으로 안/밖에 있는지를 판단
      • 양수: 평면 안쪽
      • 0: 평면 위
      • 음수: 평면 바깥쪽
    • 절두체는 6개 평면의 교집합이므로, 모든 평면에 대해 조건을 만족하면 내부이다.

Image

  • 중요한 규약
    • n · p + d >= 0를 내부 조건으로 쓰려면,
      평면의 법선 n절두체 내부를 향하도록 맞춰져 있어야 한다.

    • 또한 거리 기반 판정을 정확히 하려면,
      평면을 ||n|| = 1이 되도록 정규화해두는 것이 안전하다.

실제 컬링은 바운딩 볼륨으로 수행한다

메시의 모든 정점을 검사하는 대신, 오브젝트의 바운딩 볼륨(Bounding Volume)을 검사해 비용을 줄인다.

1) Bounding Sphere

Image

  • 아이디어
    • 구의 중심과 반지름만으로 빠르게 판정 가능.
  • 판정
    • dist = n · center + d
    • dist < -radius 이면 구 전체가 평면 바깥 → 컬링 가능
    • 그 외에는 내부 또는 교차(완전 컬링 불가)
  • 특징
    • 매우 빠르지만, 형태에 비해 느슨할 수 있다.

2) Bounding Box (AABB/OBB)

  • 아이디어
    • 박스로 오브젝트를 감싸고 평면과의 관계를 검사한다.
    • AABB는 축 정렬이라 계산이 비교적 쉽고,
    • OBB는 회전까지 포함해 더 타이트하지만 계산이 더 무겁다.
  • 개념
    • 평면 법선 방향으로 “가장 불리한 점(지원점)”을 이용하면
      모든 코너를 검사하지 않고도 “완전 외부” 판정이 가능하다.

TMI - CPU 절두체 컬링의 한계와 GPU-driven 컬링

  • CPU 절두체 컬링이 비효율적일 수 있는 경우
    • 컬링 검사 자체가 너무 많을 때
      • 오브젝트 수가 매우 많으면(AABB/Sphere 테스트가 가볍더라도) 전체 검사 비용이 CPU에서 누적될 수 있음
    • 컬링 후에도 살아남는 오브젝트가 너무 많을 때
      • 최종적으로 제출해야 할 렌더링 후보가 많으면 그만큼 DrawCall 기록/상태 변경/커맨드 생성 비용이 증가
      • 즉, 병목이 “GPU 셰이딩”이 아니라 “CPU 제출” 쪽에서 생길 수 있음
  • 그래서 등장한 흐름: GPU-driven 컬링
    • CPU는 “엄청 많은 개별 DrawCall” 대신, 비교적 적은 수의 큰 작업을 제출하고
    • GPU가 내부에서 가시성(컬링) + LOD + 렌더링 단위 선택을 수행하는 방식
    • 대표적인 형태
      • Indirect Draw / ExecuteIndirect
        • GPU가 “그릴 목록(인자 버퍼)”을 만들고, 그 버퍼를 기반으로 그리기
      • Mesh Shader / Task Shader 기반
        • 기존 VS/GS 중심 파이프라인보다 “GPU 쪽에서 프리미티브 생성/컬링/증폭”을 유연하게 수행 가능
      • UE5 Nanite 개념
        • 렌더링 단위를 더 잘게(클러스터) 쪼개고,
        • GPU가 화면 기여도에 따라 클러스터 단위 가시성/LOD를 결정해
        • CPU의 개별 메시/폴리곤 단위 제출 부담을 줄이는 방향(“그릴 단위의 가상화/자동 선택”)

댓글남기기