Files
2nd/10_Wiki/Topics/AI_and_ML/WebSplatter (3D Gaussian Splatting).md
T
Antigravity Agent f8b21af4be Wiki cleanup: error-doc removal, dedup merge, link normalization
10_Wiki/Topics 대규모 정리:
- 오류 캡처/미완성 stub 문서 227개 제거
- 교차폴더 중복 43클러스터 병합 (63파일 → redirect)
- 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건
- 카테고리 MOC 6개 신규 생성
- Graph 섹션 미해결 related-keyword 링크 10,058건 제거

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 23:52:15 +09:00

206 lines
7.6 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-websplatter-3d-gaussian-splattin
title: WebSplatter (3D Gaussian Splatting)
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [WebSplatter, 3DGS Web Viewer, Gaussian Splatting Web]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
verification_status: applied
tags: [3dgs, gaussian-splatting, webgl, webgpu, neural-rendering]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
language: TypeScript
framework: WebGL2/WebGPU
---
# WebSplatter (3D Gaussian Splatting)
## 매 한 줄
> **"매 NeRF 의 후계자 — 매 3D scene 을 millions of anisotropic Gaussian 으로 표현, web 에서 60fps real-time render"**. 2023 SIGGRAPH (Kerbl et al.) 의 3DGS paper 가 NeRF 의 slow ray-marching 을 differentiable rasterization 으로 대체하면서 photorealistic 3D capture 가 commodity 가 되었다. 2026 현재 WebSplatter / antimatter15-splat / SuperSplat / gsplat.js 등이 매 browser 에서 native handling — Apple Vision Pro / Quest 3 immersive content 의 default format.
## 매 핵심
### 매 3DGS 본질
- **Representation**: 매 scene = N개 (보통 1M-10M) 의 3D Gaussian — 매 Gaussian 은 (position μ, covariance Σ, opacity α, SH color coefficients) 로 parametrize.
- **Rendering**: 매 differentiable rasterization — Gaussian 을 screen space ellipse 로 project 후 alpha-blend (front-to-back).
- **Training**: 매 SfM (COLMAP) sparse cloud 로 init → photometric loss + densification/pruning heuristic 으로 optimize (~30min on RTX 4090 for one scene).
### 매 NeRF 대비
- **Speed**: NeRF 매 second-per-frame, 3DGS 매 100+ fps (1080p, RTX 30 class).
- **Quality**: 매 PSNR 비슷 (Mip-NeRF 360 기준 27.4 vs 27.5), 매 sharper detail in foreground.
- **Editability**: 매 explicit primitive — 매 Gaussian 단위 select / delete / transform 가능 (NeRF 매 implicit MLP, edit 어려움).
### 매 Web 배포 challenge
1. **File size**: 1M Gaussian × 60 byte/Gaussian = 60MB raw. 매 SOG / SOGS / .ply quantize 로 ~5-10MB 까지 압축.
2. **Sort cost**: 매 frame 마다 view-dependent depth sort 필요 (correct alpha blend). 매 GPU radix sort 필수.
3. **Browser GPU**: WebGL2 매 instanced rendering hack 필요, WebGPU 매 compute shader 로 native sort.
### 매 응용
1. Real estate 3D walkthrough — 매 phone 으로 capture, 매 WebSplatter viewer 로 share.
2. E-commerce — 매 product 360 turntable.
3. VFX previz — 매 set scan 후 Unreal/Blender 로 import.
4. Cultural heritage — 매 monument digitize.
## 💻 패턴
### 1. Splat 파일 load (.splat / .ply)
```typescript
// gsplat.js style loader
import { Scene, Splat, SplatLoader } from "gsplat";
const scene = new Scene();
const loader = new SplatLoader(scene);
const splat: Splat = await loader.loadAsync(
"https://cdn.example.com/scene.splat",
(progress) => console.log(`${(progress * 100).toFixed(1)}%`)
);
console.log(`Loaded ${splat.data.vertexCount} Gaussians`);
```
### 2. Gaussian sort (WebGPU compute)
```wgsl
// depth-sort.wgsl — view-dependent radix sort
@group(0) @binding(0) var<storage, read> positions: array<vec4<f32>>;
@group(0) @binding(1) var<storage, read_write> depths: array<u32>;
@group(0) @binding(2) var<uniform> viewProj: mat4x4<f32>;
@compute @workgroup_size(256)
fn computeDepth(@builtin(global_invocation_id) gid: vec3<u32>) {
let i = gid.x;
if (i >= arrayLength(&positions)) { return; }
let clip = viewProj * vec4(positions[i].xyz, 1.0);
// negate so far → small key, near → large (back-to-front blending)
depths[i] = bitcast<u32>(-clip.z / clip.w);
}
```
### 3. Splat instanced rendering (WebGL2)
```glsl
// vertex shader — project 3D Gaussian to 2D ellipse
in vec3 a_quad; // unit quad corner [-1,1]
in vec3 a_center; // Gaussian μ
in vec3 a_cov_a; // covariance row 0
in vec3 a_cov_b; // covariance row 1
in vec4 a_color; // SH degree-0 + opacity
uniform mat4 u_viewProj;
out vec2 v_uv;
out vec4 v_color;
void main() {
vec4 clip = u_viewProj * vec4(a_center, 1.0);
// project 3D covariance to 2D screen space (Zwicker EWA splatting)
mat2 cov2d = projectCovariance(a_cov_a, a_cov_b, clip);
vec2 axis = computeMajorAxis(cov2d);
vec2 offset = a_quad.x * axis + a_quad.y * perpendicular(axis);
gl_Position = clip + vec4(offset, 0.0, 0.0);
v_uv = a_quad.xy;
v_color = a_color;
}
```
### 4. Quantize (SOG format, 2025)
```python
# self-organizing Gaussian — 90% size reduction
import torch
from sogs import SOGCompressor
splat = torch.load("scene.pt") # raw 3DGS state
compressor = SOGCompressor(
position_bits=16,
scale_bits=8,
rotation_bits=8,
sh_bits=6,
)
compressed = compressor.compress(splat)
compressor.write("scene.sog", compressed) # ~6MB instead of 60MB
```
### 5. Train custom scene (gsplat library)
```python
# Modern training pipeline (Nerfstudio + gsplat backend)
from nerfstudio.scripts.train import main as train
train([
"splatfacto", # gsplat-based pipeline
"--data", "data/my_scene",
"--max-num-iterations", "30000",
"--pipeline.model.cull-alpha-thresh", "0.1",
"--pipeline.model.densify-grad-thresh", "0.0002",
])
# Export: ns-export gaussian-splat --load-config outputs/.../config.yml
```
### 6. React + WebSplatter component
```tsx
import { Canvas } from "@react-three/fiber";
import { Splat } from "@react-three/drei";
export function SceneViewer({ url }: { url: string }) {
return (
<Canvas camera={{ position: [0, 0, 5], fov: 50 }}>
<Splat src={url} />
<orbitControls enableDamping dampingFactor={0.05} />
</Canvas>
);
}
```
### 7. Edit / mask Gaussians
```typescript
// Remove Gaussians inside bounding box (e.g., remove a person)
function maskOutBox(splat: Splat, min: Vec3, max: Vec3) {
const keep: number[] = [];
for (let i = 0; i < splat.data.vertexCount; i++) {
const p = splat.data.getPosition(i);
if (p.x < min.x || p.x > max.x || p.y < min.y || p.y > max.y) {
keep.push(i);
}
}
return splat.subset(keep);
}
```
## 매 결정 기준
| 상황 | Approach |
|---|---|
| Static scene capture (real estate, VFX previz) | 3DGS — speed + quality 둘 다 |
| Dynamic scene (humans, fluids) | 4D Gaussian Splatting (4DGS) or NeRF derivatives |
| Mobile / low-bandwidth | SOG / SOGS quantize → < 10MB |
| AR/VR (Vision Pro, Quest) | 3DGS native — Metal / Vulkan compute path |
| Editable scene | 3DGS (explicit) > NeRF (implicit MLP) |
**기본값**: gsplat (training) + WebSplatter/antimatter15-splat (web viewer) + SOG (compression).
## 🔗 Graph
- 부모: [[3D Gaussian Splatting (3DGS)]]
- 변형: [[NeRF]]
- 응용: [[Spatial_Computing|Spatial Computing]]
- Adjacent: [[WebGPU]]
## 🤖 LLM 활용
**언제**: 매 photo-realistic real-world scene 을 매 web/AR 에 deploy 하고 싶을 때. 매 capture-once-view-anywhere workflow.
**언제 X**: 매 procedurally generated content (game asset)는 매 mesh + PBR 가 여전히 우월. 매 dynamic deformable mesh, 매 physical simulation.
## ❌ 안티패턴
- **Quantize 안 하고 60MB raw 배포**: 매 mobile 에서 OOM. 항상 SOG/SOGS 거쳐야.
- **CPU sort**: 매 1M Gaussian sort 매 frame 매 100ms+. 매 GPU radix sort 필수.
- **Sparse SfM init 생략**: 매 random init 매 converge 안 함. COLMAP step skip 금지.
- **Aggressive densification**: 매 split threshold 너무 낮으면 매 30M Gaussians 폭발 → OOM.
## 🧪 검증 / 중복
- Verified (Kerbl et al. SIGGRAPH 2023, gsplat library docs, antimatter15 reference impl).
- 신뢰도 A.
## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — 3DGS web viewer + SOG compression + WebGPU sort patterns |