작성일 :

보이지 않는 것은 그리지 않는다

Unity 렌더 파이프라인 (2) - 드로우콜과 배칭에서는 배칭을 통해 CPU가 GPU에 렌더링 명령을 제출하는 비용을 줄이는 방법을 살펴보았습니다. Static Batching으로 드로우콜을 합치거나, SRP Batcher로 렌더 스테이트 전환을 줄이면 CPU 부담이 감소합니다.

하지만 배칭이 아무리 효율적이어도, 화면에 보이지 않는 오브젝트까지 GPU에 제출하면 결과가 폐기될 작업에 CPU와 GPU 모두 시간을 소비합니다. 가장 빠른 드로우콜은 아예 호출하지 않는 드로우콜입니다.

컬링(Culling)은 불필요한 드로우콜을 없애기 위해, GPU에 제출하기 전에 화면에 보이지 않는 오브젝트를 걸러내는 과정입니다.


씬에 오브젝트가 1,000개 있더라도 CPU에서 컬링을 거치면 카메라에 보이는 100개만 GPU에 제출되고, 나머지 900개는 렌더링 자체가 생략됩니다.

씬의 전체 오브젝트 (1,000개) 컬링 (Culling) ← 보이지 않는 오브젝트 제거 렌더링 대상 (100개) 배칭 (Batching) ← 드로우콜/상태 변경 줄이기 GPU 렌더링


컬링이 무엇을 렌더링할지 결정하면, 배칭은 그 결과를 받아 드로우콜을 효율적으로 묶어 GPU에 제출합니다. Unity에서는 Frustum Culling, Occlusion Culling, 레이어별 컬링 거리로 렌더링 대상을 줄이고, LOD와 텍스처 아틀라스로 남은 오브젝트의 렌더링 비용을 낮춥니다.


Frustum Culling

Frustum Culling은 카메라의 시야 영역 밖에 있는 오브젝트를 렌더링 대상에서 제외하는 기법입니다. Unity는 별도의 설정 없이 매 프레임 자동으로 수행합니다.

이 시야 영역을 뷰 프러스텀(View Frustum)이라고 합니다. 시야각(Field of View)이 각도 범위를 결정하고, 가까운 클리핑 평면(Near Clip Plane)먼 클리핑 평면(Far Clip Plane)이 렌더링 거리의 앞뒤 한계를 정합니다. Unity의 기본값은 Near가 0.3, Far가 1,000 단위입니다.

이 세 값이 만들어내는 공간은 잘린 사각뿔 형태이며, 프러스텀 안에 들어오는 오브젝트만 카메라에 보입니다.

FOV 카메라 Near Clip Plane Far Clip Plane 뷰 프러스텀 (View Frustum) 잘린 사각뿔 형태의 3D 공간 0 Near Far


바운딩 볼륨과 교차 검사

오브젝트가 프러스텀 안에 있는지 판단하려면 메쉬와 프러스텀을 비교해야 합니다. 메쉬의 삼각형 하나하나를 프러스텀의 6개 평면과 비교하면 연산이 많아, 씬의 모든 오브젝트에 매 프레임 적용하기는 어렵습니다. 대부분의 엔진은 삼각형 단위 비교 대신, 오브젝트를 감싸는 단순한 도형이 프러스텀과 겹치는지만 검사합니다.

Unity가 이 교차 검사에 사용하는 도형은 AABB(Axis-Aligned Bounding Box), 오브젝트를 감싸는 가장 작은 직육면체입니다. Axis-Aligned(축 정렬)라는 이름대로 각 변이 항상 월드 좌표축(x, y, z)에 평행합니다. 방향이 고정되어 있으므로, 각 축에서 오브젝트가 차지하는 범위(예: x 2~5, y 1~4, z 3~7)만으로 직육면체의 위치와 크기가 모두 정해집니다.

이 범위를 프러스텀의 6개 평면과 비교하면 교차 여부를 바로 판단할 수 있습니다.

y x z 오브젝트 (메쉬) (2, 1, 3) (5, 4, 7) AABB 범위: x = 2~5, y = 1~4, z = 3~7 각 변이 좌표축에 평행 → 여섯 개의 숫자로 형태 결정


AABB가 6개 평면(상, 하, 좌, 우, Near, Far) 중 하나라도 완전히 바깥에 있으면 프러스텀 외부로 판정합니다.

Far Near A B C 카메라 A: 프러스텀 안에 포함 → 렌더링 B: 경계에 걸침 → 렌더링 (보수적 판정) C: 프러스텀 밖 → 제거


AABB가 프러스텀 경계에 걸치는 경우(B)에는 보수적으로 렌더링 대상에 포함합니다. 실제로는 메쉬의 일부만 보일 수 있지만, AABB 단위로는 이를 정확히 구분할 수 없기 때문입니다.


Frustum Culling의 비용과 효과

AABB와 평면의 교차 검사는 오브젝트 하나당 6개 평면과의 비교 연산만 수행합니다. 오브젝트 1,000개를 검사해도 CPU에서 수십 마이크로초(µs) 수준에 끝나면서, 프러스텀 밖의 오브젝트 전부를 렌더링에서 제외할 수 있습니다.

특히, 카메라가 씬의 일부만 바라보는 일반적인 상황에서 Frustum Culling은 렌더링 대상을 크게 줄여줍니다. 넓은 오픈 월드에서 카메라가 한 방향을 바라보면, 뒤쪽과 좌우 먼 곳의 오브젝트가 모두 제거됩니다.

하지만 프러스텀 안에 있더라도 건물이나 벽에 가려져 보이지 않는 경우까지는 걸러내지 못합니다. 이 부분을 담당하는 것이 Occlusion Culling입니다.


Occlusion Culling

Occlusion Culling은 프러스텀 안에 있지만 다른 물체에 완전히 가려진(occluded) 오브젝트를 렌더링 대상에서 제외하는 기법입니다. 건물 뒤의 가구, 벽 뒤의 방, 산 뒤편의 마을처럼 화면에 나타나지 않는 오브젝트가 대상입니다.

카메라 건물 (벽) Occluder ← 가리는 오브젝트 가려진 영역 가구 (테이블) Occludee ← 가려진 오브젝트 Frustum 안에 있지만 보이지 않음 → Occlusion Culling으로 제거

Unity의 Occlusion Culling: 베이크 방식

가려짐 여부는 카메라 위치와 오브젝트들 사이의 앞뒤 관계에 따라 달라지므로, 매 프레임 계산하면 비용이 커질 수 있습니다.

Unity는 이 부담을 런타임에서 빌드 타임으로 옮기는 베이크(Bake) 방식을 사용합니다. 에디터에서 미리 씬을 분석하여 각 위치에서 어떤 오브젝트가 보이는지를 계산해 두고, 런타임에는 이 결과를 조회만 합니다.

1. 씬을 3D 셀(Cell)로 분할 C00 C01 C02 C03 C10 C11 C12 C13 C20 C21 C22 C23 C30 C31 C32 C33 x y z 2. 각 셀에서 보이는 오브젝트 목록 C11 → {건물A, 나무B, 도로C, ...} C12 → {건물A, 울타리D, ...} C21 → {나무B, 도로C, 건물E, ...} 3. 바이너리 데이터로 저장


베이크를 실행하면 Unity는 씬 공간을 3D 격자(Cell)로 나누고, 건물이나 벽 같은 정적 오브젝트(Occluder)의 메쉬를 단순한 블록(복셀)으로 변환합니다. 그런 뒤 각 셀에서 블록에 완전히 막혀 도달할 수 없는 오브젝트를 제외하고, 나머지를 해당 셀의 가시 목록으로 저장합니다.

런타임 동작

런타임에는 카메라의 현재 위치가 어느 셀에 해당하는지를 찾고, 그 셀의 가시 목록을 조회합니다. 가시 목록에 없는 오브젝트는 렌더링 대상에서 제외됩니다.

카메라 위치 → 셀 C11에 해당 C11의 가시 목록 조회 {건물A, 나무B, 도로C} 가시 목록에 없는 오브젝트 → 렌더링 제외 (건물E, 울타리D, 가구F 등)


이 조회는 씬 로드 시 RAM에 올라온 베이크 데이터에서 셀을 찾고 가시 목록을 참조하는 것이므로, 런타임에 가시성을 새로 계산하는 것에 비해 부담이 작습니다.

베이크 방식의 제약

베이크 방식은 런타임 비용을 줄이지만, 베이크 시간, Occluder의 정적 제한, 메모리 사용이라는 제약이 따릅니다.

씬이 크고 복잡할수록 베이크 시간이 길어집니다. 셀 수와 오브젝트 수가 많을수록 각 셀에서의 가시성 계산량이 증가하며, 대규모 씬에서는 수십 분 이상 소요되기도 합니다.

Occluder는 정적 오브젝트로 제한됩니다. Occluder의 위치와 형태가 베이크 데이터에 기록되어 있으므로, 런타임에 위치가 바뀌는 동적 오브젝트(캐릭터, 이동하는 플랫폼 등)는 Occluder가 될 수 없습니다. 다만 동적 오브젝트라도 Occludee(가려지는 역할)로는 등록할 수 있습니다. Occluder가 고정되어 있는 만큼, 동적 오브젝트가 그 뒤에 있는지는 런타임에 판단할 수 있기 때문입니다.

베이크된 가시성 데이터는 씬과 함께 저장되고, 런타임에 메모리에 로드됩니다. 셀이 세밀할수록, 오브젝트가 많을수록 데이터 크기가 커집니다. 모바일처럼 가용 메모리가 제한된 환경에서는 셀 크기를 지나치게 줄이지 않도록 주의해야 합니다.


씬 구조에 따른 Occlusion Culling 효과

Occlusion Culling의 효과는 씬에서 시야를 차단하는 구조물이 얼마나 있느냐에 따라 달라집니다. 건물 내부에서는 벽 뒤 다른 방이, 도시에서는 건물 뒤편이 가려져 렌더링 대상이 크게 줄어듭니다. 반면, 평원이나 사막처럼 탁 트인 환경에서는 오브젝트 대부분이 실제로 보이므로 제거할 대상이 적습니다.


레이어별 컬링 거리

Frustum Culling과 Occlusion Culling을 거쳐도, 풀 한 포기, 작은 돌, 파티클 이펙트 같은 오브젝트가 카메라에서 200m 떨어져 있으면 화면에서 한두 픽셀 크기로 나타나, 시각적 효과는 거의 없지만 렌더링 비용은 그대로 발생합니다.

레이어별 컬링 거리(Per-Layer Culling Distance)는 오브젝트 종류마다 컬링 거리를 두어, 그 밖의 오브젝트를 렌더링에서 제외하는 방식입니다. Unity에서는 오브젝트를 레이어로 분류한 뒤, Camera.layerCullDistances로 레이어마다 컬링 거리를 지정할 수 있습니다. 풀 레이어에 30m, 소품 레이어에 80m를 설정하면 해당 거리 밖의 풀과 소품이 렌더링에서 제외됩니다.

컬링 거리 측정 방식

컬링 거리를 지정하지 않은 레이어는 카메라의 Far Clip Plane을 그대로 사용합니다.

기본적으로 컬링 거리는 카메라 전방 축(z축)에 대한 투영 거리로 측정됩니다. 투영 거리란 오브젝트가 카메라 전방 축을 따라 얼마나 앞에 있는지를 나타내는 값으로, 옆이나 위아래 방향의 거리는 포함되지 않습니다. 카메라 정면의 오브젝트는 거의 전방에만 떨어져 있으므로 직선 거리와 투영 거리가 거의 같습니다. 화면 가장자리에 보이는 오브젝트는 카메라에서 옆으로 치우쳐 있으므로, 같은 직선 거리라도 투영 거리는 짧아집니다.

전방 축 카메라 컬링 거리 80m A (정면) 투영 100m ≈ 직선 100m 80m 초과 → 제거 B (가장자리) 직선 100m 투영 ≈ 65m 80m 이내 → 렌더링


이 때문에 카메라를 회전하면 같은 오브젝트의 투영 거리가 달라집니다. 직선 거리 100m인 오브젝트가 화면 중앙에 있을 때는 투영 거리도 약 100m이지만, 카메라를 회전하여 화면 가장자리로 밀려나면 투영 거리가 줄어듭니다. 컬링 거리가 80m라면, 중앙에서는 80m를 넘어 제거되지만 가장자리에서는 80m 안에 들어와 다시 나타납니다. 카메라 회전만으로 오브젝트가 갑자기 나타나거나 사라질 수 있습니다.

투영 거리 대신 카메라로부터의 직선 거리(반경)로 컬링하면 이 문제가 사라집니다. 직선 거리는 카메라 회전에 영향받지 않으므로 오브젝트의 컬링 여부가 안정적으로 유지됩니다. Unity에서는 Camera.layerCullSpherical을 true로 설정하여 이 방식을 사용할 수 있습니다.


효과와 주의점

레이어 하나에 거리를 지정하면 해당 레이어의 오브젝트 전체에 적용되므로, 풀·돌·파티클처럼 개수가 많은 오브젝트도 한 번의 설정으로 처리할 수 있습니다.

다만 컬링 거리가 짧을수록, 플레이어가 이동할 때 오브젝트가 갑자기 나타나는 팝인(Pop-in)이 눈에 띕니다.


LOD 시스템 실전

컬링은 보이지 않는 오브젝트를 제거하지만, 화면에 보이는 오브젝트는 그대로 렌더링해야 합니다. LOD(Level of Detail)는 카메라에서 먼 오브젝트의 메쉬를 단순한 버전으로 교체하여 정점 수를 줄이는 방식입니다. 기본 개념은 렌더링 기초 (1) - 메쉬의 구조에서 다루었습니다.

LOD 단계 전환

Unity에서 LOD는 LODGroup 컴포넌트로 동작합니다. 하나의 LODGroup 안에 여러 단계(LOD 0, LOD 1, LOD 2, …)가 있고, 각 단계에 서로 다른 복잡도의 메쉬가 들어갑니다. LOD 0이 가장 정밀한 원본 메쉬이고, 숫자가 올라갈수록 삼각형 수가 줄어듭니다.

단계 전환의 기준은 카메라와의 절대 거리가 아니라 화면 점유 비율(Screen Relative Height)입니다. 오브젝트의 바운딩 볼륨이 화면 높이에서 차지하는 비율이 줄어들면 다음 단계로 전환됩니다. 큰 건물은 100m 떨어져도 화면 비율이 높아 LOD 0을 유지하지만, 작은 돌은 20m만 떨어져도 비율이 낮아 LOD 2로 전환됩니다.

LOD 전환과 Cross Fade

LOD 단계가 바뀔 때 메쉬가 순간적으로 교체되면, 삼각형 수 차이로 인해 실루엣이 급변하는 팝핑(Popping) 현상이 발생합니다. 이를 완화하기 위해 Unity의 LODGroup은 Fade Mode 설정을 제공합니다.

None은 전환 시점에서 메쉬를 즉시 교체합니다. 추가 비용이 없지만, 팝핑이 발생합니다.

Cross Fade는 전환 시점 전후로 이전 LOD와 다음 LOD를 동시에 렌더링하면서 투명도를 전환합니다. 이전 LOD가 점점 투명해지고 다음 LOD가 점점 불투명해지므로 전환 자체는 부드럽습니다. 하지만 전환 구간에서는 두 단계의 메쉬가 같은 픽셀을 모두 기록하므로 오버드로우(Overdraw)가 발생하여 렌더링 비용이 일시적으로 증가합니다.

SpeedTree는 나무와 식생 모델 생성 미들웨어인 SpeedTree 에셋 전용 모드입니다. Cross Fade와 유사하게 전환 구간에서 블렌딩을 수행하지만, 나뭇잎이나 가지처럼 복잡한 실루엣의 식생에 맞게 조정된 방식을 사용합니다.


디더링 기반 Cross Fade

디더링(Dithering) 기반 Cross Fade는 두 LOD를 투명도로 섞는 대신, 픽셀 위치를 체크무늬처럼 나누어 한 픽셀에 한쪽 LOD만 그리는 방식입니다.

일반 Cross Fade (투명도 블렌딩) LOD 0 50% 투명 LOD 1 50% 투명 → 모든 픽셀을 두 번 기록 디더링 Cross Fade (체크무늬 패턴) LOD 0 LOD 1 → 각 픽셀을 한 번만 기록


전환이 진행될수록 이전 LOD가 담당하는 픽셀은 줄어들고 다음 LOD의 픽셀은 늘어납니다. 각 픽셀이 한 번만 기록되므로, 일반 Cross Fade의 오버드로우가 발생하지 않습니다.

다만 픽셀 기록과 셰이더 연산은 다릅니다. GPU는 양쪽 LOD의 프래그먼트 셰이더를 모든 픽셀에 대해 실행한 뒤, 디더링 패턴에 해당하지 않는 결과를 clip()으로 버립니다. 버리는 시점이 셰이더 실행 이후이므로 연산은 이미 수행된 상태이고, 드로우콜도 양쪽 LOD 각각 발생합니다. 디더링이 줄이는 것은 오버드로우(픽셀 기록 횟수)이지, 셰이더 연산이나 드로우콜이 아닙니다.

전환 구간에서는 디더링 패턴이 미세하게 보일 수 있고, 모바일처럼 해상도가 낮은 환경에서는 더 드러납니다. 하지만 모바일 GPU는 프레임버퍼에 기록할 수 있는 픽셀 수(필레이트, Fill Rate)가 제한적이어서 오버드로우의 비용이 크므로, 패턴이 보이더라도 디더링 방식이 유리한 경우가 많습니다.

모바일에서의 LOD 설계

모바일에서는 GPU 성능과 메모리가 제한적입니다. LOD 단계가 많으면 그만큼 메쉬 에셋이 늘어나 메모리 사용량이 커지고, 화면에서 충분히 작아질 때까지 고폴리곤 메쉬를 유지하도록 설정하면 GPU에 부담이 됩니다.

그래서 단계 수는 적게, 전환은 일찍 일어나도록 보수적으로 설정합니다.

화면 점유 비율 100% 25% 10% 3% 0% LOD 0 삼각형 100% LOD 1 삼각형 40% LOD 2 삼각형 15% Culled 삼각형 0% 가까움 멀어짐 괄호 안의 값은 LOD 0 대비 삼각형 수 비율


LOD 단계 사이의 삼각형 감소율이 클수록 정점 처리 비용 절약이 크지만, 전환 시 실루엣 차이가 커져 팝핑이 눈에 띄기 쉽습니다. 위 다이어그램에서 LOD 1의 삼각형 수는 LOD 0의 40%이므로, 정점 처리 비용은 60% 줄어들면서도 실루엣 변화는 비교적 완만합니다.

마지막 Culled 단계는 오브젝트를 아예 렌더링하지 않는 단계입니다. 화면에서 3% 미만을 차지하는 오브젝트는 대부분 눈에 띄지 않으므로 제거해도 시각적 차이가 작습니다. 다만, 랜드마크 건물이나 주요 지형처럼 멀리서도 존재감이 필요한 오브젝트는 Culled 대신 LOD 2를 유지하는 편이 자연스럽습니다.


텍스처 아틀라스

컬링과 LOD는 렌더링 대상의 수와 복잡도를 줄이는 방식이지만, 텍스처 아틀라스는 접근이 다릅니다. 여러 텍스처를 하나의 큰 텍스처에 합쳐, 오브젝트를 그릴 때마다 발생하는 텍스처 바인딩 변경(GPU 상태 전환)을 줄입니다.

Unity 렌더 파이프라인 (2) - 드로우콜과 배칭에서 다루었듯이 GPU는 상태 머신이고, 텍스처 교체는 비용이 큰 상태 전환 중 하나입니다. 나무, 풀, 돌, 울타리가 각각 다른 텍스처를 쓰면 오브젝트를 바꿀 때마다 텍스처를 교체해야 하지만, 하나의 아틀라스를 공유하면 텍스처가 바인딩된 상태 그대로 여러 오브젝트를 그릴 수 있습니다.

나아가 같은 텍스처를 사용하면 머티리얼 통일도 가능해집니다. Static Batching은 같은 머티리얼을 사용하는 오브젝트끼리만 배칭할 수 있는데, 아틀라스 덕분에 머티리얼이 달랐던 오브젝트들이 배칭 대상이 됩니다. 정적 오브젝트라면 Static Batching으로 메쉬를 합쳐 드로우콜을 줄일 수 있습니다.

UV 좌표 조정

UV 좌표는 메쉬의 정점이 텍스처의 어느 위치를 가리키는지 나타내는 2D 좌표입니다. 개별 텍스처에서는 UV가 (0, 0)에서 (1, 1)까지 텍스처 전체를 가리키지만, 아틀라스에서는 해당 오브젝트의 텍스처가 차지하는 영역만 가리키도록 조정됩니다.

개별 텍스처 UV (0,0)~(1,1) → 전체 참조 나무 울타리 아틀라스 (1장) UV 범위가 영역별로 나뉨 나무 울타리 (0, 0.5)~(0.5, 1.0) (0.5, 0.5)~(1.0, 1.0) (0, 0)~(0.5, 0.5) (0.5, 0)~(1.0, 0.5) (0,0) (0.5,0) (1,0) (0,0.5) (0,1)


나무 오브젝트의 UV를 (0, 0)~(1, 1)에서 (0, 0.5)~(0.5, 1.0)으로 변환하면, 아틀라스에서 나무 텍스처가 위치한 왼쪽 위 영역만 참조하게 됩니다. 실제로는 아틀라스 생성 도구나 모델링 도구가 텍스처 배치와 UV 변환을 처리하므로, 좌표를 직접 계산할 일은 거의 없습니다.

2D와 3D에서의 아틀라스

2D(Sprite Atlas): Unity는 여러 스프라이트를 하나의 아틀라스로 합치는 Sprite Atlas 기능을 제공합니다. UI 아이콘, 2D 캐릭터 스프라이트, 타일맵 등을 지정하면 빌드 시 아틀라스가 자동 생성되고 UV도 함께 조정됩니다.

3D(Texture Atlas): 3D 메쉬는 오브젝트 표면을 감싸는 복잡한 UV 레이아웃을 가지고 있어, 아틀라스에 맞게 UV를 재배치하는 작업이 필요합니다. Unity에는 이를 자동으로 처리하는 기능이 없으므로, 3D 모델링 도구(Blender, Maya 등)에서 텍스처를 합치고 UV를 조정합니다. 씬에서 자주 함께 등장하는 오브젝트를 같은 아틀라스로 묶으면 효과적입니다.


아틀라스의 크기와 제약

모바일에서는 아틀라스 크기로 1024x1024 또는 2048x2048이 일반적이며, 4096x4096도 가능하지만 메모리 부담이 큽니다. 2048x2048 아틀라스에 256x256 텍스처를 넣으면 최대 64개(8×8)가 들어갑니다.

텍스처 사이에는 패딩(Padding)을 두어, 샘플링 시 인접 텍스처의 색상이 경계를 넘어 번지는 블리딩(Bleeding)을 방지합니다. 패딩만큼 실제 넣을 수 있는 텍스처 수는 줄어듭니다.

GPU는 텍스처를 통째로 메모리에 로드하므로, 아틀라스 안의 텍스처 중 일부만 사용되더라도 전체 아틀라스가 메모리에 올라갑니다. 아틀라스가 크고 사용하지 않는 영역이 많으면 그만큼 메모리가 낭비됩니다.


최적화 기법 비교

지금까지 다룬 기법들은 렌더링 비용을 서로 다른 방식으로 줄입니다.

기법 역할 동작 시점 추가 비용
Frustum Culling 프러스텀 밖 오브젝트 제거 매 프레임 자동 거의 없음
Occlusion Culling 가려진 오브젝트 제거 오프라인 베이크 + 런타임 조회 베이크 시간, 메모리
레이어별 컬링 거리 레이어별로 먼 오브젝트 제거 매 프레임 자동 거의 없음
LOD 화면 비율에 따라 메쉬 단순화 매 프레임 자동 LOD 메쉬 에셋
텍스처 아틀라스 텍스처 바인딩 변경 감소, 머티리얼 통일 사전 준비 UV 조정, 아틀라스 메모리

이 기법들은 서로 배타적이지 않으며 함께 적용됩니다.

런타임 (매 프레임) 씬의 전체 오브젝트 (1,000개) Frustum Culling 프러스텀 밖 700개 제거 → 남은 300개 Occlusion Culling 가려진 100개 제거 → 남은 200개 레이어별 컬링 거리 먼 거리 50개 제거 → 남은 150개 LOD 삼각형 수 감소 + Culled 30개 → 남은 120개 GPU에 제출 (120개) 텍스처 아틀라스 (사전 준비) 상태 전환 감소 사전 준비 (에셋 단계)

마무리

  • Frustum Culling은 카메라의 프러스텀 밖에 있는 오브젝트를 GPU에 제출하지 않으며, Unity가 매 프레임 자동으로 수행합니다.
  • Occlusion Culling은 에디터에서 정적 Occluder의 가시성을 베이크한 뒤, 런타임에 Occludee가 가려져 있는지를 테이블 조회로 판정합니다.
  • Per-Layer Culling Distance는 레이어별로 컬링 거리를 다르게 설정하여, 멀리 있는 작은 오브젝트를 먼저 제거합니다.
  • LOD는 화면 점유 비율에 따라 메쉬의 폴리곤 수를 단계적으로 줄여 GPU 부하를 낮춥니다.
  • 텍스처 아틀라스는 여러 텍스처를 하나로 합쳐 텍스처 바인딩 변경을 줄이고, 머티리얼 통일을 통해 Static Batching 조건을 만듭니다.

각 기법은 파이프라인의 서로 다른 지점에서 비용을 줄이며, 프로젝트의 씬 구조와 타겟 기기에 맞게 조합하여 적용합니다.


UnityPipeline 시리즈에서는 렌더 파이프라인의 구조(Part 1), 드로우콜과 배칭(Part 2), 컬링과 LOD(Part 3)를 통해 GPU 쪽 렌더링 비용을 줄이는 방법을 살펴보았습니다.

GPU 쪽 비용이 정리되면, 다음 병목은 매 프레임 실행되는 C# 스크립트, Unity API 호출, 가비지 컬렉션 같은 CPU 쪽에서 발생합니다. 스크립트 최적화 시리즈에서 이 CPU 비용을 줄이는 방법을 다룹니다.


관련 글

시리즈

전체 시리즈

Tags: LOD, Unity, 모바일, 최적화, 컬링

Categories: ,