On this page
- NeRF to 3D Gaussian Splatting
NeRF to 3D Gaussian Splatting
NeRF
Mildenhall, Ben, et al. “Nerf: Representing scenes as neural radiance fields for view synthesis.” Communications of the ACM 65.1 (2021): 99-106. citation 20378 (26.07.16 기준)

3D Gaussian Splatting
Kerbl, Bernhard, et al. “3d gaussian splatting for real-time radiance field rendering.” ACM Trans. Graph. 42.4 (2023): 139-1. citation 10811 (26.07.16 기준) github

- NeRF와 3D Gaussian Splatting은 모두 여러 시점의 RGB 이미지로부터 장면을 학습하고, 새로운 카메라 시점의 이미지를 생성하는 Novel View Synthesis 방법. 두 방법의 가장 큰 차이는 다음과 같다.
NeRF는 장면을 MLP 내부의 implicit radiance field로 표현하고, ray marching으로 렌더링
3D Gaussian Splatting은 장면을 explicit Gaussian primitive의 집합으로 표현하고, rasterization으로 렌더링
3DGS는 단순히 NeRF의 MLP를 빠르게 만든 방법이라기보다, 장면의 표현 방식과 렌더링 방식을 바꾼 방법 으로 보는것이 정확
1. NeRF: 장면을 함수로 표현

NeRF는 장면을 다음과 같은 연속 함수로 표현
\[F_\theta(\mathbf{x},\mathbf d) \rightarrow (\mathbf c,\sigma)\]
\(\mathbf{x}=(x,y,z)\): 3D 공간상의 위치
\(\mathbf d\): 해당 위치를 바라보는 방향
\(\mathbf c=(r,g,b)\): 색상
\(\sigma\): volume density
즉, NeRF의 MLP에 다음과 같이 질문하는 것
“3D 공간의 이 위치를 이 방향에서 보았을 때, 어떤 색과 밀도를 가지는가?”
밀도는 주로 위치에 의존 \(\sigma=\sigma(\mathbf{x})\)
색상은 위치뿐 아니라 보는 방향에도 의존 \(\mathbf c=\mathbf c(\mathbf{x},\mathbf d)\)
이 표현방식 덕에 같은 표면도 보는 방향에 따라 색이 달라지는 반사, 광택 등의 view-dependent appearance를 표현할 수 있다.
Implicit representation
NeRF에는 점, mesh, voxel과 같은 장면 요소가 명시적으로 저장되어 있지 않다.
장면의 geometry와 appearance가 MLP의 weight 안에 암묵적으로 저장.
따라서 특정 위치의 정보를 알고 싶으면 반드시 좌표를 MLP에 입력해야 한다.
\(\mathbf{x},\mathbf d \rightarrow \text{MLP query} \rightarrow \mathbf c,\sigma\)
이러한 이유로 NeRF를 implicit neural representation이라고 부른다.
2. NeRF는 어떻게 픽셀을 렌더링하는가?
카메라 이미지의 각 픽셀에는 하나의 ray가 대응한다.

\[\mathbf r(t)=\mathbf o+t\mathbf d\]
\(\mathbf o\): 카메라 중심
\(\mathbf d\): 픽셀 방향
\(t\): ray를 따라 이동한 거리
컴퓨터는 ray 위의 모든 위치를 연속적으로 계산할 수 없으므로, 여러 지점을 sampling한다.
\(\mathbf x_i=\mathbf r(t_i)\)
각 sample을 NeRF에 입력한다.
\(F_\theta(\mathbf r(t_i),\mathbf d) \rightarrow (\mathbf c_i,\sigma_i)\)
그 후 앞쪽 sample부터 색상을 누적해 최종 픽셀 색을 만든다.
\(\hat{\mathbf C}(\mathbf r) = \sum_{i=1}^{N} T_i\alpha_i\mathbf c_i\)
\(T_i=\prod_{j<i}(1-\alpha_j)\)
여기서 \(T_i\)는 ray가 \(i\)번째 sample까지 앞의 물체에 막히지 않고 도달한 정도를 의미한다.
앞쪽 sample의 opacity가 높으면 뒤쪽 sample의 기여도는 작아진다.
즉, 최종 픽셀 색상 = 앞쪽 sample 색상 - 남은 투명도를 통과한 뒤쪽 sample 색상
이 방식이 volume rendering과 *alpha compositing이다.
*alpha compositing: 앞뒤로 겹쳐 있는 색들을 각 layer의 불투명도 \(\alpha\)에 따라 합성하는 방법
3. NeRF는 왜 느린가
NeRF의 MLP를 한 번 실행하는 것만 보면 큰 비용이 아닐 수 있다.
문제는 렌더링할 때 필요한 MLP 실행 횟수이다.
\(\text{연산량} \approx \text{전체 픽셀 수} \times \text{ray당 sample 수} \times \text{MLP query 비용}\)
예를 들어 픽셀마다 하나의 ray가 있고, 하나의 ray에서 수십 또는 수백 개의 위치를 sampling한다.
각 위치마다 MLP를 실행해야 하므로, 한 장의 이미지를 렌더링할 때 매우 많은 network query가 필요하다.
또한 sampling한 위치가 빈 공간이더라도, 해당 위치가 비어 있다는 사실을 확인하려면 field를 query해야 한다.
따라서 NeRF의 주요 병목은 단순한 색상 누적이 아니라
모든 픽셀 ray를 따라 많은 3D 위치에서 MLP를 반복 평가해야 한다는 점 이다.
4. NeRF 이후의 발전 방향
NeRF 이후 연구는 크게 두 방향으로 발전
방향 1. MLP와 sampling을 더 빠르게 만들기
중요한 구간만 sampling
빈 공간을 건너뛰기
occupancy grid 사용
hash encoding 사용
작은 network와 CUDA 최적화
방향 2. 장면을 explicit structure로 저장하기
voxel/grid 기반 radiance field
point-based radiance field
명시적인 primitive 기반 표현
3D Gaussian Splatting은 두 번째 흐름을 강하게 발전시킨 방법
5. 3D Gaussian Splatting의 장면 표현
3DGS는 장면을 여러 개의 Gaussian primitive 집합으로 표현한다.
\(\mathcal G = \{ G_1,G_2,\ldots,G_N\}\)
각 Gaussian은 다음과 같은 파라미터를 가진다.
\(G_i=(\boldsymbol\mu_i,\Sigma_i,\alpha_i,\mathbf h_i)\)
- \(\boldsymbol\mu_i\): Gaussian의 3D 중심
- \(\Sigma_i\): Gaussian의 크기, 방향, 형태
- \(\alpha_i\): opacity
- \(\mathbf h_i\): 색상을 표현하는 spherical harmonics 계수
NeRF에서는 장면이 MLP weight 안에 들어 있지만, 3DGS에서는 Gaussian들이 메모리에 직접 저장된다.
따라서 3DGS는 explicit representation이다.
Gaussian은 단순한 점이 아니다
Gaussian은 중심 위치만 가지는 point가 아니라 공간적으로 퍼져 있는 타원체이다.

복잡한 3D 장면을 수천에서 수백만 개의 3차원 가우시안으로 표현하는 방식.
각 Gaussian은 다음 정보를 가진다.
3D 위치 (x, y, z)
크기 (scale 또는 covariance)
회전 (orientation)
불투명도 (alpha)
색상 (RGB)
뷰 방향 의존적인 특성 값
이러한 점들을 화면 상에 투영하고, GPU에서 가우시안 형태로 부드럽게 퍼지게 만들어 실시간으로 이미지를 렌더링하는 것이 핵심
6. 왜 Anistropic Gaussian을 사용하는가
3DGS의 Gaussian은 모든 방향으로 동일한 구형이 아니라, 방향에 따라 크기가 다른 타원체이다.
이를 anisotropic Gaussian이라고 한다.
예를 들어 벽을 표현하는 경우,
- 벽의 가로 방향으로는 크게
- 세로 방향으로도 크게
- 벽의 두께 방향으로는 매우 작게
Gaussian을 만들 수 있다.
이렇게 하면 벽, 바닥, 모서리, 얇은 표면 등을 적은 수의 primitive로 효율적으로 표현할 수 있다.

Ground Truth, Anisotropic, Isotropic
Covariance parameterization
Gaussian의 형태는 covariance matrix로 표현된다.
\(\Sigma=RSS^TR^T\)
\(S\): 축별 크기를 결정하는 scale matrix
\(R\): Gaussian의 방향을 결정하는 rotation matrix
Scale로 타원체의 모양을 만들고, rotation으로 원하는 방향으로 회전시킨다고 이해하면 된다.
Covariance를 직접 최적화하지 않는 이유는 gradient update 이후 잘못된 covariance가 만들어질 수 있기 때문이다.
? covariance matrix를 직접 학습하면 발생하는 문제?
3D covariance는 대칭행렬이므로 형태는 다음과 같다.
\(\Sigma= \begin{bmatrix} a&b&c\\ b&d&e\\ c&e&f \end{bmatrix}\)
이를 gradient descent로 직접 업데이트하면 \(\Sigma \leftarrow \Sigma-\eta \nabla_\Sigma\mathcal{L}\) 업데이트 후 eigenvalue 중 일부가 음수가 될 수 있다. (covariance matrix의 eigenvalue는 특정 방향으로의 분산을 의미)
즉, 처음에는 유효한 covariance여도 unconstrained gradient update 한 번으로 잘못된 covariance가 될 수 있다. 이 문제 때문에 covariance를 직접 최적화하지 않는다.
? covariance matrix를 scale matrix \(S\)와 rotation matrix \(R\)로 구성하는 이유?
Gaussian의 타원체를 생각하면 모양을 두 단계로 만들 수 있다.
축별로 늘이거나 줄임
원하는 방향으로 회전
Scale matrix
\(S= \begin{bmatrix} s_x&0&0\\ 0&s_y&0\\ 0&0&s_z \end{bmatrix}\)
예를 들어 \(S=\text{diag(2, 1, 0.1)}\) 이라면, 첫 번째 축으로 길게, 두 번째 축으로 보통, 세 번째 축으로 매우 얇은 타원체가 된다.
벽을 표현한다면 두 축은 크고, 한 축은 매우 작게 만들 수 있다.
Rotation matrix
\(S\)만 사용하면 타원체 축이 world coordinate의 \(x,y,z\)축에 고정됨. 벽이나 경사진 면은 다양한 방향을 향하므로 회전 \(R\)이 필요
논문에서는 rotation을 *quaternion으로 저장한 뒤 rotation matrix \(R\)로 변환
*quaternion: 스칼라 값 w와 3차원 벡터 (x, y, z)로 구성되며, 회전축과 회전 각도를 나타냄
Covariance 구성
최종 covariance는 \(\Sigma=RSS^TR^T\)로 만든다.
\(S\)가 diagonal이라면
\(SS^T= \begin{bmatrix} s_x^2&0&0\\ 0&s_y^2&0\\ 0&0&s_z^2 \end{bmatrix}\)이고, \(R\)이 이를 원하는 방향으로 회전시킨다.
이 parameterization이 항상 유효한 covariance를 만드는 이유는 임의의 \(\mathbf{v}\)에 대해
\(\begin{aligned} \mathbf v^T\Sigma\mathbf v &= \mathbf v^TRSS^TR^T\mathbf v\\ &= (S^TR^T\mathbf v)^T(S^TR^T\mathbf v)\\ &= \|S^TR^T\mathbf v\|^2\\ &\geq0 \end{aligned}\) 이기 때문.
즉, 어떤 \(S, R\)을 사용하더라도 covariance가 자동으로 positive semi-definite가 된다.
- 실제로 역행렬을 안정적으로 사용하려면 보통 positive definite가 필요하고, positive semi-definite는 축 하나가 0에 가까운 퇴화된 경우까지 포함하는 더 일반적인 조건
위와 같이 scale과 rotation으로 구성하면 다음 성질이 유지된다.
\(\mathbf v^T\Sigma\mathbf v =\|S^TR^T\mathbf v\|^2 \geq0\)
즉, 모든 방향에서 분산이 음수가 되지 않는 유효한 covariance를 안정적으로 구성할 수 있다
7. 3D Gaussian을 이미지에 렌더링하는 방법
3D 공간의 Gaussian을 그대로 이미지에 그릴 수는 없다.
따라서 현재 카메라 시점에서 각 3D Gaussian을 이미지 평면으로 projection한다.
\(\text{3D Gaussian} \rightarrow \text{2D elliptical Gaussian}\)
3D covariance는 카메라 변환과 projection Jacobian을 통해 2D covariance로 변환된다.
\(\Sigma_{\text{2D}} \approx JW\Sigma W^TJ^T\)
\(W\): world 좌표에서 camera 좌표로의 변환
\(J\): perspective projection의 Jacobian
결과적으로 3D 타원체는 화면 위의 2D 타원형 footprint가 된다.
이 타원형 영역을 splat이라고 한다.
8. Tile-based rasterization
3DGS는 화면을 여러 개의 작은 tile로 나누어 렌더링한다.
전체 과정은 다음과 같다.
카메라 밖에 있는 Gaussian 제거
보이는 Gaussian을 2D ellipse로 projection
Gaussian이 겹치는 화면 tile 계산
각 tile에 관련 Gaussian 배치
Gaussian을 depth 순서로 정렬
앞에서 뒤로 alpha blending
정렬할 때 사용되는 depth는 카메라 좌표계에서 Gaussian 중심까지의 깊이다.
NeRF와 가장 큰 차이는 다음과 같다.
NeRF
픽셀마다 ray를 만들고, ray 위의 많은 위치를 sampling한 뒤 MLP를 반복 실행한다.
3DGS
실제로 존재하는 Gaussian을 화면에 한 번 projection하고, Gaussian이 겹치는 tile과 픽셀에서만 기여도를 계산한다.
9. 3DGS의 학습
3DGS도 NeRF와 마찬가지로 렌더링결과와 실제 이미지가 같아지도록 학습한다.

전체 과정은 다음과 같다.
SfM sparse points → Gaussian 초기화 → 현재 카메라에서 rendering → GT 이미지와 비교 → Gaussian 파라미터 업데이트 → density control로 Gaussian 추가/삭제
초기 Gaussian 위치는 일반적으로 SfM에서 얻은 sparse point cloud를 이용한다.
- COLMAP의 sparse reconstruction pipeline을 사용하여 카메라 내부 파라미터(K)와 외부 파라미터(R, t)를 추출. 이 과정에서 sparse point cloud도 함께 생성

- SfM 초기화 여부에 따른 성능 차이
최적화되는 파라미터는 다음과 같다.
위치
scale
rotation
opacity
spherical harmonics 색상
Loss는 렌더링 이미지와 실제 이미지 사이의 차이로 구성된다.
\(\mathcal L=(1-\lambda)\mathcal L_1 + \lambda\mathcal L_{\text{D-SSIM}}\)
NeRF와 3DGS 모두 photometric reconstruction loss를 사용한다.
다만 최적화 대상이 다르다.
NeRF: MLP weights
3DGS: Gaussian parameters
10. Adaptive Density Control
3DGS 학습은 기본적으로 각 점(Gaussian)의 위치, 크기, 색상 등 파라미터를 gradient descent 방식으로 최적화하는 과정. 하지만 최적화만으로는 렌더링 품질 향상에 한계가 있기 때문에 점 집합 구조 자체를 조정하는 보조 과정을 수행 (Adaptive Density Control - Pruning, Desnsification)
3DGS는 학습 중 Gaussian의 개수와 배치를 조정한다.

Clone
Gaussian이 특정 위치로 이동하면서 세부 구조를 추가로 표현해야 할 때 복제한다.
Split
Gaussian 하나가 너무 큰 영역을 표현하고 있으면 여러 개의 작은 Gaussian으로 분할한다.
Prune
opacity가 매우 낮거나 불필요한 Gaussian을 제거한다.
즉, 3DGS는 Gaussian의 파라미터뿐 아니라, 장면을 구성하는 primitive의 수와 분포까지 함께 최적화한다.
11. 3DGS Inference Pipeline
학습된 3D Gaussian Splatting 결과는 수많은 3D Gaussian들이고, 결과믈은 .ply 또는 .gs 파일로 저장됨. 이를 통해 실시간 렌더링이 가능한 인터랙티브 뷰어 구성 가능. 사용자가 뷰를 회전하거나 확대할 때, GPU에서 즉시 장면을 렌더링하여 즉각적인 반응성을 제공.
아래는 3DGS Inference Pipeline 과정이다.
학습된 가우시안 데이터 로드
Gaussian들의 파라미터 (\(\bold{x}, \Sigma, RGB, \alpha\) 등…)를 GPU 메모리로 로드
일반적으로 수십만~수백만 개의 점으로 구성
카메라 매트릭스 반영
사용자의 Viewport 입력을 바탕으로 카메라의 내외부 파라미터(K, R, t)를 계산
모든 가우시안들을 카메라 좌표계로 변환한 뒤 투영
Z-정렬 (Depth sorting)
카메라에서 가까운 점부터 그리기 위해 각 점을 카메라 기준 z-값으로 정렬
알파 블렌딩 기반의 누적 블렌딩에 필요
스플래팅 (Splatting)
학습된 각 가우시안 점은 화면에 2차원 타원 형태의 분포(Anisotropic Gaussian Ellipse)로 투영됨
각 3D Gaussian은 위치뿐 아니라 방향성과 크기(공분산 행렬 \(\Sigma\))를 지닌 타원체로 구성되어 있다.
이 3D 타원체를 카메라로 바라보면, 시점에 따라 길쭉하거나 눌린 형태의 2D 타원으로 보이게 된다.
이렇게 투영된 2D 타원은 마치 가우시안 분포처럼 흐릿하게 퍼져있는 색의 번짐 영역으로 간주되며, 각 픽셀에 영향을 준다.
- GPU에서는 이 점들을 Compute Shader 또는 Hybrid Rasterizer로 처리하여 각 타원이 해당 픽셀에 얼마나 기여할지를 계산하고, Z 정렬된 순서대로 알파 블렌딩(alpha compositing)하여 누적 렌더링을 수행
프레임 출력
모든 픽셀의 색상/깊이 정보를 결합하여 최종 이미지 생성
60FPS 이상으로 실시간 출력 가능
12. NeRF와 3DGS 비교
장면 표현
NeRF
\(F_\theta(\mathbf{x},\mathbf d) \rightarrow (\mathbf c,\sigma)\)
장면이 MLP weight 안에 저장된 implicit representation이다.
3DGS
\(\mathcal G = \{G_1,G_2,\ldots,G_N\}\)
\(G_i=(\boldsymbol\mu_i,\Sigma_i,\alpha_i,\mathbf h_i)\)
장면이 Gaussian primitive 집합으로 직접 저장된 explicit representation이다.

| 항목 | NeRF | 3D Gaussian Splatting |
|---|---|---|
| 표현 방식 | 좌표 → MLP (암시적) | 가우시안 점 구름 (명시적) |
| 렌더링 | 레이 마칭·적분 | GPU 래스터·알파 블렌딩 |
| 훈련 시간 | 수 시간~수 일 | 수 분 |
| 추론 속도 | 수 ms ~ 수백 ms | 수 μs → 60 FPS+ |
| 메모리 | 수~수십 MB | 수백 MB ~ 수 GB (점 개수) |
| 편집 난이도 | MLP 재학습 필요 | 점 속성 직접 수정 |
| 아티팩트 | 노이즈, blur | 메모리 폭, occlusion bleed |
| 장점 요약 | 압축·저메모리 | 실시간·편집성 |
Nerf ↔︎ 3DGS 구도는 메모리·압축성 vs 속도·편집성 trade off라고 이해하면 쉽다.
13. 최종 정리
NeRF의 핵심은 다음과 같다.
장면을 MLP 기반 radiance field로 표현하고, ray 위의 위치를 sampling한 뒤 volume rendering으로 픽셀을 생성한다.
하지만 렌더링할 때 모든 픽셀의 ray 위에서 많은 MLP query가 필요하므로 느리다.
3DGS는 다음과 같이 변경한다.
장면을 직접 최적화되는 anisotropic Gaussian primitive의 집합으로 표현하고, Gaussian을 화면에 projection하여 rasterization한다.
따라서 NeRF 수준의 novel view synthesis 품질을 유지하면서도 실시간 렌더링이 가능해졌다.
가장 중요한 변화는 다음 두 가지다.
\(\text{Implicit MLP field} \rightarrow \text{Explicit Gaussian primitives}\)
\(\text{Ray marching} \rightarrow \text{Projection and rasterization}\)
다만 빠른 렌더링을 얻는 대신, 많은 Gaussian으로 인한 메모리 사용량과 정확하지 않은 geometry라는 새로운 문제가 생겼다.
? 3DGS의 정확하지 않은 geometry의 이유?
3DGS의 학습 목적이 주로 다음과 같은 이미지 재현 오차를 줄이는 데 있기 때문
\(\mathcal{L}=(1-\lambda)\mathcal{L}_1\)+\(\lambda\mathcal{L}_{\text{D-SSIM}}\)
즉, Gaussian이 실제 표면에 정확히 놓였는지를 직접 감독하기보다, 렌더링한 이미지가 입력 이미지와 비슷한지를 최적화하기 때문
3DGS
Limitation
메모리 사용량이 크다
학습 view와 겹치지 않는 시점에서는 artifact가 생길 수 있다.
큰 scene에서는 하이퍼파라미터 조정이 필요할 수 있다.
표면 mesh가 아니다
Contribution
Anisotropic 3D Gaussian을 radiance field의 explicit representation으로 도입
Gaussian parameter optimization과 adaptive density control을 결합
Visibility-aware, differentiable, GPU-friendly rasterizer 제안