docs(10_Wiki): Topic_Business/General/Graphic/Programming을 Topics/ 하위로 이동
최상위 10_Wiki/Topic_*였던 4개 카테고리 폴더를 10_Wiki/Topics/Topic_* 로 재배치. 콘텐츠 변경 없음(순수 폴더 이동) — Topics/ 하위 나머지 폴더는 이미 지난 커밋에서 전부 정리된 상태(잔존 항목은 에이전트 운영 상태 및 사용자가 보존을 요청한 업데이트0615/무제 3.canvas 뿐).
This commit is contained in:
+210
@@ -0,0 +1,210 @@
|
||||
---
|
||||
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); // 0–50
|
||||
lod.addLevel(midMesh, 50); // 50–200
|
||||
lod.addLevel(lowMesh, 200); // 200–500
|
||||
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]]
|
||||
- Adjacent: [[bitECS와 SharedArrayBuffer를 결합한 멀티스레드 고성능 아키텍처]] · [[Frustum 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) |
|
||||
Reference in New Issue
Block a user