드로우콜 최적화
인스턴싱, HLOD, 머티리얼 배칭으로 GPU 효율 극대화
드로우콜이란?
CPU에서 GPU로의 렌더링 명령
드로우콜(Draw Call)은 CPU가 GPU에게 "이 오브젝트를 렌더링하라"고 보내는 명령입니다. 각 드로우콜에는 오버헤드가 있으므로, 드로우콜 수를 줄이는 것이 CPU 성능 최적화의 핵심입니다.
// 드로우콜 수 확인
stat scenerendering
// 주요 항목:
// - Mesh Draw Calls: 메시 드로우콜 수
// - Draw Primitive Calls: 전체 드로우 프리미티브 호출
// - Static Mesh Instances: 정적 메시 인스턴스 수
PC에서는 2000-3000 드로우콜, 콘솔에서는 1000-2000 드로우콜이 권장됩니다. Nanite를 사용하면 이 제한이 크게 완화됩니다.
드로우콜 감소 기법
다양한 최적화 기술
동일 메시를 하나의 드로우콜로 여러 개 렌더링
여러 메시를 하나로 병합
거리에 따른 계층적 LOD
머티리얼 수 최소화
Instanced Static Mesh
동일 메시 인스턴싱
동일한 메시를 여러 번 배치할 때 InstancedStaticMeshComponent를 사용하면 하나의 드로우콜로 수천 개의 인스턴스를 렌더링할 수 있습니다.
UCLASS()
class AFoliageManager : public AActor
{
GENERATED_BODY()
public:
AFoliageManager()
{
InstancedMesh = CreateDefaultSubobject<UInstancedStaticMeshComponent>(
TEXT("InstancedMesh"));
RootComponent = InstancedMesh;
}
void AddInstances(const TArray<FTransform>& Transforms)
{
for (const FTransform& Transform : Transforms)
{
InstancedMesh->AddInstance(Transform, true);
}
}
void RemoveInstance(int32 Index)
{
InstancedMesh->RemoveInstance(Index);
}
void UpdateInstanceTransform(int32 Index, const FTransform& NewTransform)
{
InstancedMesh->UpdateInstanceTransform(Index, NewTransform, true, true);
}
private:
UPROPERTY(VisibleAnywhere)
UInstancedStaticMeshComponent* InstancedMesh;
};
UE 5.5부터 동일한 메시와 머티리얼을 가진 Static Mesh Actor들이 자동으로 배칭됩니다. 하지만 대규모 배치에는 여전히 ISM을 직접 사용하는 것이 효율적입니다.
HLOD (Hierarchical LOD)
대규모 오픈월드 필수
HLOD는 먼 거리의 여러 오브젝트를 하나의 단순화된 메시로 대체하여 드로우콜을 극적으로 줄입니다.
가까운 거리, 개별 오브젝트
중간 거리, 인스턴싱 또는 병합
먼 거리, 단순화된 메시
매우 먼 거리, 임포스터
HLOD 빌드
// 에디터에서
Build > Build HLODs
// 커맨드라인 (자동화)
-run=WorldPartitionHLODsBuilder -map=/Game/Maps/MyLevel
// HLOD 레이어 타입
// - Instancing: 인스턴싱된 메시
// - Merged Mesh: 병합된 단일 메시
// - Simplified Mesh: 단순화된 메시
// - Approximated Mesh: 근사 메시
머티리얼 최적화
머티리얼 수와 복잡도 감소
동일한 머티리얼을 사용하는 메시는 배칭될 수 있습니다. 머티리얼 수를 최소화하면 드로우콜이 줄어듭니다.
- 텍스처 아틀라스 - 여러 텍스처를 하나로 합쳐 머티리얼 공유
- 머티리얼 인스턴스 - 파라미터만 다른 경우 인스턴스 사용
- 머티리얼 슬롯 최소화 - 메시당 머티리얼 슬롯 수 줄이기
- 동적 머티리얼 피하기 - 런타임 머티리얼 생성 최소화
// 머티리얼 인스턴스 동적 생성 (필요한 경우만)
void AMyActor::SetupMaterial()
{
if (BaseMaterial)
{
// 동적 인스턴스 생성
DynamicMaterial = UMaterialInstanceDynamic::Create(
BaseMaterial, this);
MeshComponent->SetMaterial(0, DynamicMaterial);
}
}
// 파라미터 변경
void AMyActor::SetColor(FLinearColor Color)
{
if (DynamicMaterial)
{
DynamicMaterial->SetVectorParameterValue(
FName("BaseColor"), Color);
}
}
Nanite에서는 삼각형 수보다 머티리얼 수가 성능에 더 큰 영향을 미칩니다. 머티리얼 슬롯을 최소화하세요.
핵심 요약
- stat scenerendering - 드로우콜 수 확인
- InstancedStaticMeshComponent - 동일 메시 인스턴싱
- HLOD - 먼 거리 오브젝트 병합/단순화
- 머티리얼 최소화 - 텍스처 아틀라스, 인스턴스 활용
- Nanite 활용 - 자동 LOD로 드로우콜 부담 감소
- 목표 - PC 2000-3000, 콘솔 1000-2000 드로우콜
도전 과제
배운 내용을 직접 실습해보세요
stat SceneRendering으로 드로우콜 수를 확인하세요. RenderDoc이나 내장 GPU Visualizer로 드로우콜이 많은 오브젝트를 식별하고, Mesh Merging 또는 Instancing으로 최적화하세요.
동일 셰이더의 머티리얼 바리에이션을 Material Instance로 통합하여 머티리얼 변경 횟수를 줄이세요. 색상/텍스처만 다른 RPG 아이템들은 하나의 Parent Material에서 Instance를 파생하세요.
UInstancedStaticMeshComponent와 UHierarchicalInstancedStaticMeshComponent를 활용하여 대량의 동일 메시(나무, 풀, 바위)를 하나의 드로우콜로 렌더링하세요. 인스턴스 수에 따른 성능 측정을 수행하세요.