Files
2nd/10_Wiki/Topics/Programming & Language/가변적 LOD(Level of Detail) 시스템.md
T
2026-05-10 22:08:15 +09:00

212 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: wiki-2026-0508-가변적-lod-level-of-detail-시스템
title: 가변적 LOD(Level of Detail) 시스템
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [LOD, Level of Detail, dynamic LOD, mesh simplification]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
verification_status: applied
tags: [graphics, gamedev, rendering, lod, optimization]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
language: TypeScript
framework: Three.js / Bevy / Unreal Nanite
---
# 가변적 LOD(Level of Detail) 시스템
## 매 한 줄
> **"매 LOD = 매 distance/screen-size 에 따라 매 mesh detail 을 매 동적 교체"**. 매 close 매 high-poly, 매 far 매 low-poly. 매 fixed-bucket LOD (LOD0/1/2/3) 매 classic, 매 continuous/clustered LOD (Unreal Nanite, Bevy meshlet) 매 2026 SOTA — 매 hierarchical cluster + GPU culling 으로 매 sub-pixel triangles 까지 매 streaming.
## 매 핵심
### 매 motivation
- 매 GPU 매 triangle/pixel budget 유한.
- 매 멀리 있는 mesh 의 매 millions of triangles 매 1픽셀에 매 수십 — 매 waste + aliasing.
- 매 적절한 detail 매 close → 매 가까이 모이는 비용 ↓, 매 visual quality ↑.
### 매 LOD 종류
1. **Discrete LOD**: 매 N개의 pre-built mesh, 매 distance threshold 에서 swap. 매 popping 가능.
2. **Continuous LOD (CLOD)**: edge-collapse 매 progressive mesh, 매 smooth transition. 매 CPU heavy.
3. **Hierarchical LOD (HLOD)**: 매 region-level 매 single mesh 병합 (먼 city block → 1 mesh).
4. **Cluster/Meshlet LOD** (Nanite, Bevy 0.13+): 매 mesh를 매 ~128-tri cluster 로 분해 + 매 BVH, 매 GPU 가 매 cluster 단위로 매 select.
5. **Imposter / Billboard**: 매 texture 1장으로 매 멀리서 fake.
6. **Tessellation LOD**: 매 GPU tess shader 가 매 dynamic subdivide.
### 매 selection criteria
- **Distance**: euclidean distance 매 가장 단순.
- **Screen-space size**: bounding sphere → projected pixel size — 매 정확.
- **Velocity / motion**: 매 빠른 object 매 lower LOD 가용.
- **Importance**: 매 player focus / center → high LOD.
### 매 응용
1. **Open-world game**: terrain, vegetation, building.
2. **Voxel world**: chunk LOD by distance.
3. **Crowd rendering**: 매 distant NPC 매 imposter.
4. **Vegetation**: tree → bush → billboard.
5. **CAD 시각화**: 매 model assembly 매 distant simplify.
## 💻 패턴
### Pattern 1: Three.js LOD basic
```typescript
import * as THREE from "three";
const lod = new THREE.LOD();
lod.addLevel(highMesh, 0); // 050
lod.addLevel(midMesh, 50); // 50200
lod.addLevel(lowMesh, 200); // 200500
lod.addLevel(billboard, 500); // 500+
scene.add(lod);
// renderer 가 매 frame 마다 camera.position 으로 자동 select
```
### Pattern 2: screen-space size 기반
```typescript
function selectLOD(obj: THREE.Object3D, camera: THREE.Camera) {
const sphere = new THREE.Sphere();
obj.traverse((c) => {
if (c instanceof THREE.Mesh) c.geometry.computeBoundingSphere();
});
const dist = camera.position.distanceTo(obj.position);
const fov = (camera as THREE.PerspectiveCamera).fov * Math.PI / 180;
const screenH = window.innerHeight;
const projected = (sphere.radius / dist) / Math.tan(fov / 2) * screenH;
if (projected > 200) return 0; // high
if (projected > 50) return 1; // mid
if (projected > 10) return 2; // low
return 3; // billboard
}
```
### Pattern 3: voxel chunk LOD
```typescript
// each chunk has 4 mesh resolutions
type Chunk = { x: number; z: number; meshes: [Mesh, Mesh, Mesh, Mesh] };
function chunkLOD(c: Chunk, camera: Camera): number {
const dx = c.x * CHUNK_SIZE - camera.x;
const dz = c.z * CHUNK_SIZE - camera.z;
const d = Math.sqrt(dx * dx + dz * dz);
if (d < 100) return 0;
if (d < 300) return 1;
if (d < 700) return 2;
return 3;
}
```
### Pattern 4: hysteresis (popping 완화)
```typescript
// LOD swap 시 매 threshold 에 매 hysteresis 추가
function selectLODHysteresis(dist: number, currentLOD: number): number {
const THR = [50, 200, 500];
const HYS = 10; // ±10
if (currentLOD === 0 && dist > THR[0] + HYS) return 1;
if (currentLOD === 1 && dist < THR[0] - HYS) return 0;
if (currentLOD === 1 && dist > THR[1] + HYS) return 2;
// ...
return currentLOD;
}
```
### Pattern 5: GPU instancing per LOD
```typescript
// 매 LOD level 별 매 InstancedMesh, 매 entity 매 batch
const instancedHigh = new THREE.InstancedMesh(highGeo, mat, MAX);
const instancedMid = new THREE.InstancedMesh(midGeo, mat, MAX);
// per frame: 매 entity 의 LOD 결정 → 매 해당 instance 행렬 update
```
### Pattern 6: Bevy meshlet (2026)
```rust
// Bevy 0.13+ — meshlet rendering (cluster LOD)
use bevy::pbr::experimental::meshlet::*;
commands.spawn((
MeshletMesh3d(asset_server.load("model.meshlet_mesh")),
Transform::default(),
));
// GPU 가 매 cluster bvh + screen-space error 로 자동 select
```
### Pattern 7: imposter texture (vegetation)
```glsl
// fragment shader: 매 distance > THRESHOLD → 매 sample atlas billboard
uniform float u_distToCam;
uniform sampler2D u_imposterAtlas;
void main() {
if (u_distToCam > 200.0) {
vec4 imp = texture(u_imposterAtlas, vUV);
if (imp.a < 0.5) discard;
gl_FragColor = imp;
} else {
// full mesh shading
}
}
```
### Pattern 8: progressive mesh (edge collapse offline)
```typescript
// build time: 매 mesh → edge collapse sequence
type Collapse = { v0: number; v1: number; targetVertex: number };
const collapses: Collapse[] = simplify(mesh);
// runtime: 매 LOD level k → apply collapses[0..k]
function applyLOD(mesh: Mesh, level: number) {
for (let i = 0; i < level; i++) collapseEdge(mesh, collapses[i]);
}
```
### Pattern 9: HLOD region merge
```typescript
// 매 build time: cluster 9 buildings → 1 merged mesh per region
// runtime: distance > 1km → region mesh, < 1km → individual buildings
```
## 매 결정 기준
| 상황 | Approach |
|---|---|
| 게임 props (rocks, trees) | Discrete LOD + imposter |
| Open-world terrain | Quadtree HLOD |
| Voxel/Minecraft | Chunk LOD by ring |
| Crowd (1k+ NPC) | Instancing + LOD + imposter |
| Modern AAA / engine 자체 | Nanite / Bevy meshlet |
| Scientific visualization | CLOD edge collapse |
**기본값**: discrete LOD 3-tier + imposter. 매 engine 이 cluster LOD 매 지원하면 우선.
## 🔗 Graph
- 부모: [[Rendering]] · [[Optimization]]
- 변형: [[Nanite]] · [[Meshlet]] · [[Progressive Mesh]] · [[Imposter]]
- 응용: [[Voxel Engine]] · [[Open World]] · [[Vegetation Rendering]]
- Adjacent: [[bitECS와 SharedArrayBuffer를 결합한 멀티스레드 고성능 아키텍처]] · [[Frustum Culling]] · [[Occlusion Culling]]
## 🤖 LLM 활용
**언제**: 매 large scene, 매 다양한 distance, 매 GPU/CPU bound. 매 1k+ object scene.
**언제 X**: 매 small scene (single character), 매 fixed camera distance — overhead 만 추가.
## ❌ 안티패턴
- **Anti1: hard popping**: hysteresis/dither 없이 매 instant swap — 매 시각적 jarring.
- **Anti2: 매 LOD level 별 mesh 따로 load**: 매 GPU memory 폭발. 매 progressive 또는 매 streaming.
- **Anti3: distance only metric**: 매 huge object 매 멀어도 화면 큼 — screen-size 사용.
- **Anti4: 매 tick 마다 LOD 재계산 every entity**: 매 batch / spatial hash 로 매 amortize.
- **Anti5: imposter 의 매 stale lighting**: 매 shadow / time-of-day 안 맞음 — 매 atlas 재생성 필요.
## 🧪 검증 / 중복
- Verified (Unreal Nanite paper SIGGRAPH 2021, Bevy 0.13 meshlet docs, Three.js LOD).
- 신뢰도 A.
## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — LOD strategies + 2026 cluster LOD (Nanite/Meshlet) |