Nanite 실전 활용
오픈월드에서의 Nanite 최적화와 HLOD 연동
Nanite와 HLOD 연동
원거리 렌더링 최적화
Nanite는 근거리에서 탁월하지만, 오픈월드의 극원거리 오브젝트에는 HLOD(Hierarchical LOD)와 함께 사용해야 최적의 성능을 얻습니다.
// Content Browser에서 HLOD Layer Asset 생성
// Miscellaneous > HLOD Layer
HLOD Layer Settings:
Layer Type: MeshMerge // 또는 Instancing, Simplified
Cell Size: 12800 // 셀 크기 (cm)
Loading Range: 25600 // 로딩 거리
Mesh Merge Settings:
Generate Nanite Enabled Mesh: true // HLOD도 Nanite 사용!
Use Landscape Culling: true // 가려진 삼각형 제거
Allow Distance Field: false // 원거리용 DF 불필요
계층적 HLOD 구성
/*
거리별 HLOD 레이어 구성 예시:
┌─────────────────────────────────────────────────────────────┐
│ 거리 0 ~ 128m │ 소스 메시 (Nanite) │
├─────────────────────────────────────────────────────────────┤
│ 거리 128m ~ 512m │ HLOD Layer 1 (Merged, Nanite) │
├─────────────────────────────────────────────────────────────┤
│ 거리 512m ~ 2km │ HLOD Layer 2 (Simplified, Nanite) │
├─────────────────────────────────────────────────────────────┤
│ 거리 2km+ │ HLOD Layer 3 (Impostor/Billboard) │
└─────────────────────────────────────────────────────────────┘
*/
// C++에서 HLOD Layer 할당
#include "WorldPartition/HLOD/HLODLayer.h"
void AssignHLODLayer(AActor* Actor, UHLODLayer* Layer)
{
if (Actor && Layer)
{
// 액터의 HLOD 레이어 설정
if (UPrimitiveComponent* Prim = Actor->FindComponentByClass<UPrimitiveComponent>())
{
// 에디터에서 Details > HLOD에서 설정하는 것과 동일
}
}
}
Nanite Foliage (UE 5.3+)
식생에 Nanite 적용하기
UE 5.3부터 폴리지에 Nanite를 사용할 수 있습니다. 수십만 개의 나무 인스턴스를 효율적으로 렌더링할 수 있습니다.
// Foliage Type Asset에서 설정
Mesh:
Static Mesh: SM_Tree_Oak // Nanite 활성화된 메시
Nanite:
Enable Nanite: true // 폴리지에서 Nanite 사용
Painting:
Density: 100
Radius: 500
메모리 최적화 사례
| 항목 | 기존 LOD | Nanite Foliage |
|---|---|---|
| 나무 디스크 용량 | 3.5GB | 29MB |
| 스트리밍 메모리 | 36MB | 2.7MB |
| 인스턴스 수 | 제한적 | 500,000+ |
WPO와 Nanite
World Position Offset 사용 시 주의사항
WPO(World Position Offset)는 Nanite와 VSM(Virtual Shadow Maps)에서 큰 성능 비용을 발생시킵니다. 반드시 Disable Distance를 설정하세요!
// Material Editor > Details
World Position Offset:
WPO Disable Distance: 5000 // 50m 이후 WPO 비활성화
// 또는 머티리얼 노드에서
[Distance To Nearest Surface] --> [If] --> [WPO Output]
^
Distance Check
C++에서 WPO 제어
// 동적으로 WPO 거리 설정
void AWindController::UpdateWPODistance(float PlayerDistance)
{
// 프로젝트 설정에서 글로벌 WPO 거리 조정
static IConsoleVariable* WPODistanceCVar =
IConsoleManager::Get().FindConsoleVariable(
TEXT("r.Nanite.MaxWPODistance"));
if (WPODistanceCVar)
{
// 플레이어 상황에 따라 동적 조절
float OptimalDistance = FMath::Clamp(PlayerDistance * 0.5f, 2000.0f, 10000.0f);
WPODistanceCVar->Set(OptimalDistance);
}
}
WPO 적합
- 바람에 흔들리는 잎
- 물결 효과
- 깃발 펄럭임
WPO 부적합
- 대규모 지형 변형
- 항상 보이는 오브젝트
- 그림자 필수 오브젝트
C++ 프로그래밍 통합
런타임에서 Nanite 제어하기
#include "Engine/StaticMesh.h"
// 메시의 Nanite 설정 읽기
void UMyBlueprintFunctionLibrary::GetNaniteInfo(
UStaticMesh* Mesh,
bool& bEnabled,
int32& TriangleCount)
{
if (Mesh)
{
bEnabled = Mesh->NaniteSettings.bEnabled;
// Nanite 리소스에서 삼각형 수 얻기
if (bEnabled && Mesh->GetRenderData())
{
// 대략적인 삼각형 수
TriangleCount = Mesh->GetNumTriangles(0);
}
}
}
// 런타임에서 Nanite 토글 (에디터 전용)
#if WITH_EDITOR
void ToggleNanite(UStaticMesh* Mesh, bool bEnable)
{
if (Mesh)
{
Mesh->NaniteSettings.bEnabled = bEnable;
Mesh->Build(); // 재빌드 필요
}
}
#endif
// Nanite 렌더링 품질 동적 조절
void AMyGameMode::AdjustNaniteQuality(float QualityLevel)
{
// 0.0 ~ 1.0 품질 레벨
float PixelsPerEdge = FMath::Lerp(2.0f, 0.5f, QualityLevel);
IConsoleVariable* CVar = IConsoleManager::Get().FindConsoleVariable(
TEXT("r.Nanite.MaxPixelsPerEdge"));
if (CVar)
{
CVar->Set(PixelsPerEdge);
}
}
최적화 체크리스트
대규모 오픈월드 Nanite 최적화
- 고폴리 메시 — 10,000+ 삼각형 메시에 Nanite 활성화
- HLOD 연동 — 원거리용 계층적 HLOD 레이어 구성
- WPO Distance — WPO 사용 시 반드시 Disable Distance 설정
- 인스턴스 제한 — 씬당 1,600만 인스턴스 이하 유지
- 스트리밍 풀 — SSD 환경에서 적절한 풀 크기 설정
- 시각화 확인 — r.Nanite.Visualize로 클러스터 분포 확인
World Partition과 함께 사용 시, Nanite 메시는 자동으로 셀 기반 스트리밍됩니다. HLOD와 함께 사용하면 극원거리 렌더링도 최적화됩니다.
핵심 요약
- HLOD 연동 — Nanite + HLOD로 근/원거리 모두 최적화
- Nanite Foliage — UE5.3+에서 수십만 식생 인스턴스 효율적 렌더링
- WPO 주의 — Disable Distance 설정 필수, 성능 영향 큼
- 동적 제어 — 콘솔 변수로 런타임 품질 조절 가능
- World Partition — 자동 셀 기반 Nanite 스트리밍
도전 과제
배운 내용을 직접 실습해보세요
ZBrush/Blender에서 고폴리 바위 메시를 익스포트하고 UE5에 Nanite 활성화 상태로 임포트하세요. LOD 없이 수백만 폴리곤 메시가 실시간으로 렌더링되는 것을 확인하세요.
동일한 Nanite 메시를 ISM(Instanced Static Mesh) 또는 PCG로 수천 개 배치하고, stat Nanite로 드로우콜과 삼각형 수를 확인하세요. Nanite 비활성화 시와 비교하여 성능 차이를 측정하세요.
Nanite 미지원 플랫폼(모바일 등)을 위한 Fallback 메시를 설정하세요. r.Nanite.FallbackRelativeError를 조정하여 Fallback 품질과 성능의 균형을 맞추세요. 다양한 거리에서 비주얼 품질을 비교하세요.