3D GIS 지식 그래프
지리공간 기술과 프론트엔드 엔지니어링을 연결하는 인터랙티브 포트폴리오
- 3D Tiles 스펙 — 클러스터: format, 난이도: advanced
- 면적 계산 알고리즘 — Delaunay 삼각분할 + 벡터 외적 — 클러스터: geodesy, 난이도: expert
- AWS Lambda → EC2 트리거 — 클러스터: infrastructure, 난이도: intermediate
- Cesium.js 도입 결정 — 클러스터: decision, 난이도: intermediate
- Cesium 마우스 이벤트 처리 — 클러스터: frontend, 난이도: advanced
- Chrome DevTools 메모리 프로파일링 — 클러스터: problem, 난이도: intermediate
- 좌표계 변환 EPSG→WGS84→ECEF — 클러스터: geodesy, 난이도: advanced
- Docker 컨테이너 — 클러스터: infrastructure, 난이도: intermediate
- Draco 지오메트리 압축 — 클러스터: optimization, 난이도: intermediate
- FBXLoader 메모리 누수 — 클러스터: problem, 난이도: intermediate
- 지오이드고 보정 — 클러스터: geodesy, 난이도: advanced
- GPU 텍스처 BC7·ASTC·ETC2 — 클러스터: graphics, 난이도: advanced
- IFC→3D Tiles 자동 변환 파이프라인 — 클러스터: implementation, 난이도: expert
- KTX2 Basis Universal — 클러스터: optimization, 난이도: advanced
- LOD 레벨 오브 디테일 — 클러스터: graphics, 난이도: advanced
- Cesium 측정 도구 7종 — 클러스터: implementation, 난이도: advanced
- 자오선 수차 보정 — 클러스터: geodesy, 난이도: expert
- Mesh·BIM·Point Cloud — 클러스터: graphics, 난이도: beginner
- modelMatrix 위치·회전·스케일 — 클러스터: implementation, 난이도: advanced
- 낙관적 업데이트 — 클러스터: frontend, 난이도: advanced
- 공간 분할 기법 — Quadtree와 AABB — 클러스터: graphics, 난이도: advanced
LOD 레벨 오브 디테일
3D 그래픽스LOD 레벨 오브 디테일
한 줄 요약
하나의 3D 모델에 대해 여러 정밀도 단계를 생성하여, 카메라 거리에 따라 적절한 단계를 선택적으로 보여주는 기법. 정점을 원본의 2~15% 수준으로 단순화하면서 시각적 품질을 유지하는 것이 핵심이다.
LOD가 해결하는 문제
10,000개의 정점으로 이루어진 기둥 모델을 생각해보자. 카메라가 1미터 거리에 있으면 10,000개 정점이 모두 의미가 있다 — 기둥의 모서리, 곡면, 디테일이 화면에 크게 보이기 때문이다.
그런데 카메라가 1km 거리에 있으면? 이 기둥은 화면에서 겨우 몇 픽셀이다. 10,000개의 정점 중 9,990개는 화면에 아무런 차이를 만들지 않는다. 그러나 GPU는 여전히 10,000개의 정점을 모두 처리한다 — 의미 없는 연산에 메모리와 GPU를 낭비하는 것이다.
LOD는 이 문제를 "거리에 따라 정밀도를 조절하자"로 해결한다. 같은 기둥에 대해 여러 버전을 준비한다:
- LOD 0 (원본): 10,000개 정점 — 가까이서 볼 때
- LOD 1: 1,500개 정점 (15%) — 중간 거리
- LOD 2: 500개 정점 (5%) — 먼 거리
- LOD 3: 200개 정점 (2%) — 매우 먼 거리
카메라가 멀어지면 자동으로 낮은 LOD로 전환하고, 가까워지면 높은 LOD로 전환한다. 사용자는 시각적 차이를 느끼지 못하면서, 시스템은 GPU와 메모리를 절약한다.
메쉬 단순화(Mesh Simplification)의 원리
LOD의 각 단계를 생성하는 핵심 기술이 메쉬 단순화다. 원본 메쉬의 정점 수를 줄이면서, 전체적인 형상을 최대한 유지하는 알고리즘이다.
엣지 축소 (Edge Collapse)
가장 널리 사용되는 단순화 방법이다. 메쉬의 엣지(두 정점을 잇는 선분) 하나를 선택하고, 그 엣지의 두 정점을 하나로 합친다. 이 과정에서 연결된 삼각형이 함께 제거된다.
핵심은 어떤 엣지를 먼저 합칠 것인가의 순서다. 시각적 변화가 가장 적은 엣지(예: 거의 평평한 표면 위의 짧은 엣지)를 먼저 합치고, 시각적으로 중요한 엣지(예: 날카로운 모서리)는 마지막까지 보존한다.
이 우선순위를 결정하는 방법 중 하나가 QEM(Quadric Error Metrics)이다. 각 엣지를 합쳤을 때 발생하는 기하학적 오차를 수학적으로 계산하고, 오차가 가장 작은 엣지부터 순서대로 합친다.
2~15%까지 단순화해도 괜찮은 이유
"정점의 2%만 남기면 형체를 알아볼 수 없지 않은가?"라는 의문이 들 수 있다. 그러나 두 가지 이유로 실용적이다:
첫째, 먼 거리에서만 사용된다. 정점 2%의 LOD는 카메라가 수백 미터~수 km 떨어져 있을 때만 보인다. 이 거리에서 모델은 화면에서 매우 작으므로, 10,000개든 200개든 시각적 차이가 없다.
둘째, 날카로운 모서리가 우선 보존된다. QEM 같은 알고리즘은 평평한 면의 정점을 먼저 제거하고, 건물의 윤곽선이나 모서리 같은 시각적으로 중요한 정점은 마지막까지 남긴다. 그래서 98%를 제거해도 "건물의 실루엣"은 유지된다.
LOD와 geometricError의 관계
3D Tiles 스펙 노드에서 다뤘듯, geometricError는 각 타일이 원본 대비 얼마나 부정확한지를 미터 단위로 나타낸다. LOD 단계별로 geometricError를 설정하면, Cesium이 카메라 거리에 따라 적절한 LOD를 자동 선택한다.
tileset.json 구조:
root (geometricError: 500) ← LOD 3 (2%, 매우 먼 거리용)
└── children (geometricError: 100) ← LOD 2 (5%, 먼 거리용)
└── children (geometricError: 10) ← LOD 1 (15%, 중간 거리용)
└── children (geometricError: 0) ← LOD 0 (원본, 가까운 거리용)
geometricError가 큰 타일(LOD 3)은 카메라가 멀 때 사용되고, geometricError가 작은 타일(LOD 0)은 카메라가 가까울 때 사용된다. Cesium은 "이 타일의 geometricError가 화면에서 몇 픽셀로 보이는가"를 매 프레임 계산하여, 허용 임계값(기본 16픽셀)을 초과하면 더 정밀한 하위 타일을 로드한다.
LOD 생성 시 geometricError를 단순화 비율에 비례하도록 설정하는 것이 합리적이다. 예를 들어 정점을 50%로 줄인 LOD의 geometricError는, 2%로 줄인 LOD보다 작아야 한다 — 더 정밀한 모델이므로 오차가 작기 때문이다.
다만 geometricError의 정확한 값을 결정하는 것은 모델의 크기, 디테일 수준, 사용 목적에 따라 달라지는 튜닝 작업이다. "시각 품질"과 "메모리 사용량" 사이의 트레이드오프를 실제 테스트를 통해 조율해야 한다.
LOD와 공간 분할의 관계
LOD와 공간 분할(Quadtree/AABB)은 서로 다른 축의 최적화다:
- 공간 분할: "보이지 않는 타일은 로드하지 않는다" (수평 방향 최적화)
- LOD: "먼 타일은 간략하게 보여준다" (깊이 방향 최적화)
두 기법이 함께 적용되면, 카메라 시야 밖의 타일은 아예 로드하지 않고, 시야 안이지만 먼 타일은 낮은 LOD로 로드한다. 이것이 3D Tiles가 수 GB의 데이터를 웹 브라우저에서 끊김 없이 렌더링할 수 있는 핵심 메커니즘이다.
이 경험에서 추출한 원칙
-
"보이는 만큼만 처리한다"가 웹 3D 최적화의 핵심이다. LOD는 "보이는 크기에 맞는 정밀도만 제공한다"이고, 공간 분할은 "보이는 영역만 로드한다"이다. 둘 다 같은 철학의 다른 적용이다.
-
단순화의 품질은 "얼마나 줄이느냐"보다 "무엇을 보존하느냐"에 달려있다. 정점 수를 98% 줄여도 시각적으로 중요한 모서리와 윤곽선이 보존되면 실용적이다. 알고리즘이 어떤 우선순위로 정점을 제거하는지가 품질을 결정한다.