3D Gaussian Splatting 간단 정리 — 장면을 수백만 개의 타원으로 그리기
서론
이 블로그에 Robotics Vision 카테고리를 새로 엽니다. 첫 글은 최근 몇 년 사이 3D 장면 표현의 판을 바꾼 3D Gaussian Splatting(3DGS) 입니다.1
로봇에게 “공간을 안다”는 것은 결국 장면을 어떤 자료구조로 들고 있느냐의 문제입니다. 점군(point cloud), 복셀 격자, 메시, TSDF, 그리고 NeRF까지 — 각 표현은 정밀도·메모리·렌더링 속도 사이에서 서로 다른 타협을 합니다. 3DGS는 여기에 “3차원 가우시안 덩어리 수백만 개“라는 답을 내놓았고, 그 결과 NeRF급 화질을 실시간 렌더링 속도로 얻었습니다.
이 글은 3DGS가 무엇을 어떻게 표현하고, 왜 빠르며, 로보틱스에서 왜 주목받는지를 한 바퀴 정리합니다. 순서는 문제 설정 → 표현 → 렌더링 → 최적화 → 비교 → 한계입니다.
읽다가 막힌다면. 이 글이 설명 없이 지나가는 것들 — SfM, 래스터화, 알파 블렌딩, 구면 조화 함수, Adam, 미분 가능성 — 을 한 편씩 풀어 쓴 3DGS를 읽기 위한 기초지식 시리즈가 따로 있습니다. 1편 MLP와 역전파부터 순서대로 읽으면 이 글이 그대로 이해됩니다. 전체 목차는 이 글 맨 아래에 있습니다.
1. 풀려는 문제 — 새로운 시점 합성
출발점은 novel view synthesis입니다.
어떤 장면을 여러 각도에서 찍은 사진 수십~수백 장이 주어졌을 때, 사진에 없던 새로운 시점의 이미지를 만들어 내라.
입력은 이미지들과 각 이미지의 카메라 포즈입니다. 포즈는 보통 COLMAP 같은 SfM(Structure-from-Motion)으로 먼저 구합니다. SfM은 부산물로 희소 점군도 뱉는데, 3DGS는 이걸 초기값으로 재활용합니다.
2020년 NeRF는 이 문제를 이렇게 풀었습니다. 장면을 MLP 하나로 표현해, 3차원 좌표와 시선 방향을 넣으면 그 지점의 색과 밀도가 나오게 학습합니다. 렌더링할 때는 픽셀마다 광선을 쏘고 그 위에서 수십~수백 개 지점을 샘플링해 적분합니다. 화질은 훌륭했지만 광선당 MLP를 수백 번 호출하는 구조라 느렸습니다. 학습에 하루 이상, 한 프레임 렌더링에 수 초가 걸리는 일이 흔했습니다.
3DGS의 전환은 여기서 일어납니다.
장면을 함수(MLP) 로 암시적으로 두고 광선을 따라 훑는 대신, 장면을 명시적인 기하 프리미티브의 집합으로 두고 화면에 투영해서 칠한다(rasterize).
광선 마칭 대신 래스터화. 이 한 줄이 속도 차이의 대부분을 설명합니다. GPU는 원래 “프리미티브를 화면에 칠하는 일”을 하려고 만들어진 물건이니까요.
2. 표현 — 가우시안 한 개가 갖는 것
프리미티브로 왜 하필 가우시안일까요. 점은 크기가 없어 구멍이 생기고, 삼각형 메시는 위상(topology)을 바꿔 가며 최적화하기가 까다롭습니다. 3차원 가우시안은 경계가 부드럽고, 미분 가능하며, 투영해도 여전히 가우시안이라 이 둘의 단점을 피해 갑니다.
가우시안 하나는 다음 값들을 파라미터로 들고 있습니다.
| 파라미터 | 의미 | 개수 |
|---|---|---|
| 평균 $\mu$ | 3차원 공간에서의 위치 | 3 |
| 공분산 $\Sigma$ | 덩어리의 크기·납작함·방향 | 3(스케일) + 4(쿼터니언) |
| 불투명도 $\sigma$ | 얼마나 진하게 칠할지 | 1 |
| SH 계수 | 보는 방향에 따라 달라지는 색 | 48 (3차 SH 기준) |
공간상의 밀도는 익숙한 그 식입니다.
\[G(x) = \exp\!\left(-\tfrac{1}{2}(x-\mu)^\top \Sigma^{-1} (x-\mu)\right)\]여기서 중요한 구현 디테일이 하나 있습니다. $\Sigma$를 6개 값으로 직접 최적화하면 경사하강 도중 양의 정부호(positive definite) 조건이 깨져 공분산이 될 수 없는 행렬이 나옵니다. 그래서 스케일 행렬 $S$와 회전 행렬 $R$로 쪼개서 저장합니다.
\[\Sigma = R\,S\,S^\top R^\top\]이렇게 두면 $S$와 $R$이 어떤 값을 갖든 $\Sigma$는 항상 유효한 공분산입니다. 기하학적으로는 “단위 구를 축마다 늘렸다가($S$) 돌려놓은($R$) 타원체” 라는 뜻이고, 실제 저장은 스케일 벡터 3개와 쿼터니언 4개로 합니다.
색은 상수가 아니라 구면 조화 함수(spherical harmonics) 계수로 둡니다. 같은 표면이라도 보는 각도에 따라 반사광이 달라지는 현상(view-dependent effect)을 담기 위해서입니다.
왼쪽: 가우시안 하나는 위치·스케일·회전으로 정의되는 타원체다. 가운데 두 장: 색과 불투명도를 가진 가우시안을 늘려 가며 알파 블렌딩으로 합성한 결과(개념 예시, 2D). 개수가 늘수록 오른쪽 목표 장면에 가까워진다.
실제 장면 하나에는 이런 가우시안이 보통 수십만~수백만 개 들어갑니다.
3. 렌더링 — 3차원 타원체를 화면에 문지르기
3.1 투영: 3D 가우시안 → 2D 가우시안
가우시안의 좋은 성질이 여기서 나옵니다. 3차원 가우시안을 카메라 평면에 투영하면 다시 2차원 가우시안이 됩니다. 다만 원근 투영은 비선형이라, 시점 변환 $W$와 투영의 야코비안 $J$로 국소 선형 근사를 씁니다(EWA splatting).2
\[\Sigma' = J\,W\,\Sigma\,W^\top J^\top\]여기서 앞의 $2 \times 2$ 블록만 취하면 화면 위 타원 하나가 됩니다. 이 타원이 곧 화면에 문지르는(splat) 자국입니다.
3.2 합성: 앞에서 뒤로 알파 블렌딩
픽셀 하나의 색은, 그 픽셀을 덮는 가우시안들을 가까운 것부터 순서대로 쌓아 만듭니다.
\[C = \sum_{i \in \mathcal{N}} c_i\,\alpha_i \prod_{j=1}^{i-1}(1-\alpha_j), \qquad \alpha_i = \sigma_i \cdot \exp\!\left(-\tfrac{1}{2}(x - \mu'_i)^\top (\Sigma'_i)^{-1} (x - \mu'_i)\right)\]앞의 가우시안이 진할수록($\alpha$가 클수록) 뒤쪽 기여는 누적 곱 항에 눌려 사라집니다. 볼륨 렌더링의 누적 투과율(transmittance)과 정확히 같은 구조인데, 적분 대신 유한 개의 정렬된 합이라는 점이 다릅니다.
코드로 옮기면 이 정도로 짧습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np
def render(gaussians, H, W):
"""gaussians: 카메라에서 가까운 순으로 정렬된 (mu2d, cov2d, opacity, color) 목록"""
yy, xx = np.mgrid[0:H, 0:W]
C = np.zeros((H, W, 3))
T = np.ones((H, W, 1)) # 누적 투과율 Π(1-α)
for mu, cov2d, opacity, color in gaussians:
inv = np.linalg.inv(cov2d)
d = np.stack([xx - mu[0], yy - mu[1]], axis=-1)
m = np.einsum('...i,ij,...j->...', d, inv, d) # 마할라노비스 거리 제곱
alpha = (opacity * np.exp(-0.5 * m))[..., None]
C += T * alpha * color # 이 가우시안이 기여하는 몫
T *= (1.0 - alpha) # 뒤쪽은 그만큼 가려진다
if T.max() < 1e-4: # 완전히 가려졌으면 조기 종료
break
return C
실제 CUDA 구현은 여기에 두 가지를 얹습니다. 화면을 16×16 타일로 쪼개 각 타일이 자기와 겹치는 가우시안만 보게 하고, “타일 ID + 깊이”를 하나의 키로 묶어 GPU 라딕스 정렬 한 번으로 전체 순서를 잡습니다. 픽셀마다 정렬하지 않고 타일 단위로 한 번에 처리하는 것이 실시간 성능의 핵심입니다.
3.3 그리고 이 전부가 미분 가능하다
투영도, 알파 블렌딩도 모두 매끄러운 연산입니다. 따라서 렌더된 이미지의 손실을 각 가우시안의 위치·스케일·회전·불투명도·색까지 그대로 역전파할 수 있습니다. 3DGS의 진짜 기여는 “가우시안을 쓰자”는 아이디어보다도, 이걸 빠르게 해내는 미분 가능한 타일 래스터라이저를 만든 데 있습니다.
4. 최적화 — 개수까지 학습한다
학습 루프 자체는 평범합니다.
- SfM 희소 점군의 각 점 자리에 가우시안 하나씩 놓고 시작한다.
- 학습 이미지 중 하나의 시점으로 렌더링한다.
- 원본 사진과의 손실을 계산하고 Adam으로 파라미터를 갱신한다.
손실은 L1과 D-SSIM을 섞습니다(논문은 $\lambda = 0.2$).
\[\mathcal{L} = (1-\lambda)\,\mathcal{L}_1 + \lambda\,\mathcal{L}_{\text{D-SSIM}}\]특이한 건 가우시안의 개수 자체가 고정이 아니라는 점입니다. 일정 주기마다 위치 그래디언트가 큰(= 아직 잘 못 맞추고 있는) 가우시안을 골라 손봅니다. 이것을 적응적 밀도 제어(adaptive density control) 라고 합니다.
그래디언트가 큰 가우시안은 두 경우로 나뉜다. 작아서 영역을 못 덮으면 복제(clone) 해 손실이 줄어드는 방향으로 옮기고, 너무 커서 디테일을 뭉개면 분할(split) 해 스케일을 줄인다.
- 복제(clone) — 가우시안이 작은데 오차가 크면, 아직 채우지 못한 영역이 있다는 뜻. 같은 크기로 하나 더 만들어 그래디언트 방향으로 옮깁니다.
- 분할(split) — 가우시안이 큰데 오차가 크면, 하나가 너무 넓은 영역을 뭉뚱그린다는 뜻. 둘로 쪼개고 스케일을 줄입니다.
- 가지치기(prune) — 불투명도가 임계값 아래로 떨어진 가우시안은 지웁니다. 또 주기적으로 모든 불투명도를 0 근처로 리셋해서, 카메라 앞에 떠 있는 쓸모없는 덩어리(floater)가 스스로 걸러지게 합니다.
즉 모델의 크기(=가우시안 개수)가 장면의 복잡도에 맞춰 스스로 늘고 준다는 것이 이 최적화의 특징입니다. 하늘처럼 밋밋한 영역은 큰 가우시안 몇 개로, 나뭇잎처럼 복잡한 영역은 작은 가우시안 수만 개로 채워집니다.
5. NeRF와의 비교
| NeRF 계열 | 3D Gaussian Splatting | |
|---|---|---|
| 장면 표현 | MLP 가중치 (암시적) | 가우시안 집합 (명시적) |
| 렌더링 방식 | 광선 마칭 + 적분 | 투영 + 래스터화 |
| 학습 시간 | 수 시간 ~ 수십 시간 | 수 분 ~ 수십 분 |
| 렌더링 속도 | 초당 1프레임 미만도 흔함 | 1080p에서 실시간 (수십~100+ FPS) |
| 저장 용량 | 수 MB (MLP 가중치) | 수백 MB (가우시안 수백만 개) |
| 편집·조작 | 어려움 (가중치에 뒤엉켜 있음) | 쉬움 (덩어리를 직접 옮기고 지움) |
정리하면 3DGS는 메모리를 내주고 속도와 편집 가능성을 얻은 거래입니다. NeRF 쪽도 Instant-NGP 같은 해시 격자 기법으로 크게 빨라졌으니 “NeRF는 느리다”는 단정은 이제 정확하지 않습니다. 다만 명시적 표현이라 장면의 일부를 떼어내고 옮기고 합칠 수 있다는 성질은 3DGS 쪽의 구조적 강점입니다.
6. 로보틱스에서 왜 보는가
렌더링 논문이 왜 로봇 카테고리 첫 글인지 이야기할 차례입니다.
① 지도 표현으로서의 3DGS. SLAM의 지도는 전통적으로 점군이나 TSDF였습니다. 3DGS를 지도로 쓰면 같은 자료구조 위에서 위치 추정과 사실적 렌더링을 동시에 할 수 있습니다. SplaTAM, MonoGS 같은 연구가 이 방향입니다.3 카메라 포즈에 대해서도 미분이 되기 때문에, “렌더한 이미지와 실제 관측이 일치하도록 포즈를 최적화”하는 트래킹이 자연스럽게 나옵니다.
② 시뮬레이션 자산. 실제 공간을 몇 분 만에 스캔해 사실적인 3D 자산으로 바꿀 수 있습니다. 정책 학습이나 sim-to-real 검증에 쓸 환경을 현실에서 직접 떠 오는 셈입니다.
③ 내비게이션·조작. 실시간 렌더링이 되니 후보 경로를 따라가며 “그 시점에서 뭐가 보일지”를 미리 그려볼 수 있고, 가우시안이 명시적 위치를 가지므로 충돌 검사나 파지점 추정 같은 기하 질의도 붙일 수 있습니다.
7. 한계
- 기하가 정확하지는 않다. 3DGS의 손실은 “사진과 얼마나 비슷한가”만 봅니다. 시점 의존 색이 형상 오류를 가려 주기 때문에, 잘 보이는데 표면은 틀린 결과가 나올 수 있습니다. 충돌 회피처럼 기하 정확도가 중요한 용도에는 그대로 쓰기 어렵습니다.
- 메모리. 장면 하나에 수백 MB는 임베디드 보드에 부담입니다. 압축·가지치기 연구가 활발한 이유입니다.
- 정적 장면 전제. 원본은 움직이지 않는 장면을 가정합니다. 사람이 지나다니는 공간은 4D/deformable 확장이 필요합니다.
- 입력 의존성. SfM 포즈가 틀어지면 결과도 무너집니다. 텍스처 없는 벽, 반사면, 관측이 성긴 영역은 여전히 취약합니다.
- 앨리어싱. 학습 때와 다른 해상도·거리에서 보면 화질이 무너지는 문제가 알려져 있고, Mip-Splatting 등이 이를 다룹니다.
이 한계들이 그대로 후속 연구의 목록이기도 합니다. 표면 복원을 겨냥한 2D Gaussian Splatting과 SuGaR, 앨리어싱을 다루는 Mip-Splatting, 동적 장면용 4D/Deformable 3DGS, 그리고 각종 압축 기법이 지금도 쏟아지고 있습니다.
마치며
3DGS를 한 문장으로 줄이면 이렇습니다.
장면을 수백만 개의 색칠된 3차원 타원체로 두고, 화면에 투영해 앞에서 뒤로 겹쳐 칠한다. 그 전 과정이 미분 가능하므로, 사진과 맞춰 가며 타원체의 모양·색·개수를 전부 학습한다.
핵심 아이디어 세 가지만 기억하면 충분합니다.
- 표현 — 가우시안, 그리고 $\Sigma = RSS^\top R^\top$ 라는 안전한 파라미터화.
- 렌더링 — 투영 후 타일 단위 정렬 + 알파 블렌딩. 광선 마칭이 아니라 래스터화라 빠르다.
- 최적화 — 파라미터뿐 아니라 개수까지 복제·분할·가지치기로 학습한다.
다음 글에서는 이 글이 전제로 깔고 넘어간 부분 — 여러 장의 사진에서 카메라 포즈가 어떻게 나오는가 — 으로 한 걸음 돌아가, 다중 시점 기하의 출발점인 에피폴라 기하를 다룹니다. 그 길을 따라가면 결국 가우시안 지도 위의 SLAM으로 이어집니다.
이 시리즈 — 3DGS를 읽기 위한 기초지식
- MLP와 역전파
- SGD에서 Adam까지
- SfM 파이프라인
- MVS — 밀집 복원
- 래스터화
- 알파 블렌딩과 볼륨 렌더링
- 구면 조화 함수
- 미분 가능 렌더링
- NeRF
- 3D Gaussian Splatting ← 지금 읽는 글
참고문헌
Kerbl, B., Kopanas, G., Leimkühler, T., & Drettakis, G. (2023). 3D Gaussian Splatting for Real-Time Radiance Field Rendering. ACM Transactions on Graphics (SIGGRAPH 2023), 42(4). ↩︎
Zwicker, M., Pfister, H., van Baar, J., & Gross, M. (2001). EWA Volume Splatting. IEEE Visualization 2001. — 3DGS의 투영 공식은 이 EWA splatting 계보를 따릅니다. ↩︎
Keetha, N. et al. (2024). SplaTAM: Splat, Track & Map 3D Gaussians for Dense RGB-D SLAM. CVPR 2024. / Matsuki, H. et al. (2024). Gaussian Splatting SLAM. CVPR 2024. ↩︎