Kapitel 8 — 내보내기 형식


이미지에서 볼 수 있는 것: 각 형식 타일 아래의 크기 표시는 현재 가우시안 개수와 형식별 오버헤드로부터 실시간으로 계산된 값이며 — 하드코딩된 값이 아니다. 같은 씬에서 2.2 MB PLY, 142 KB cPLY, 89 KB SOG, 216 KB SPZ, 2.1 MB glTF, 279 KB .splat이 생성된다. Web은 뷰어가 파일 안에 함께 들어 있기 때문에 378 KB로 더 크다. Video와 Wiggle은 "Zero KB"로 표시되는데, 크기는 인코딩이 끝난 뒤에야 확정되기 때문이다. 선택된 타일은 파란 테두리로 표시되며, 그 아래 버튼은 타일의 이름을 그대로 물려받는다 — 여기서는 "Export PLY (3DGS Standard)". 제목 아래에는 "Leveling the floor turns the view at once; the chosen orientation and format apply when saving"라는 문구가 있다.
학습이 끝나면 가우시안 클라우드 — 씬을 함께 재구성하는 수십만에서 수백만 개의 3D 가우시안 분포의 모음 — 이 만들어진다. 이 장에서는 이 클라우드를 디스크에 기록하는 열 가지 방법을 설명한다. 그중 여섯 가지는 순수한 3D 데이터 형식(PLY, Compressed PLY, SPZ, SOG, glTF, .splat)이고, 하나는 클라우드를 완성된 HTML 뷰어와 함께 묶으며(Web Viewer), 하나는 Orbit 카메라 이동으로부터 MP4 파일을 렌더링하고(Orbit Video), 나머지 두 개는 가우시안 콘텐츠가 아니라 SfM 결과(카메라 포즈와 대략적인 점군)만을 다른 학습 파이프라인에서 재사용할 수 있도록 내보낸다(transforms.json + COLMAP 워크스페이스).
이 중 여덟 가지 방법은 내보내기 영역에 타일로 준비되어 있다 — transforms.json과 COLMAP 워크스페이스는 메뉴에만 있다. 격자에는 그 외에 아홉 번째 타일인 Wiggle이 있고, 내보내기 버튼 아래에는 Upload to SuperSplat…가 있어 씬을 파일로 저장하는 대신 바로 인터넷의 SuperSplat 에디터로 전송한다.
어떤 형식이 언제 적절한지는 목적에 달려 있다. 품질 손실 없이 전체 데이터를 보관하려면 PLY를 사용한다. 자신의 웹사이트용 웹 뷰어에는 대개 .splat이나 내장 웹 뷰어로 충분하다. 파일이 최소한이어야 한다면 SPZ나 SOG가 유리하다. SfM 결과를 Nerfstudio, Postshot, Brush 등에서 재사용하려면 transforms.json과 COLMAP 워크스페이스가 올바른 방법이다.
모든 내보내기 기능은 "Export" 메뉴와 심플 모드의 마지막 마법사 단계에 있다. 대부분의 형식은 완전히 샌드박스에 적합하며 앱스토어 버전에서도 작동한다. SOG만은 외부 바이너리(cwebp)가 필요한데, 앱스토어 빌드에는 반드시 있는 것은 아니다 — 자세한 내용은 E4 참조.
E1 — PLY (.ply)
위치
메뉴 바 → Export → 3D Formats → Export PLY… (⌘E). 심플 모드: 마법사 단계 Export → 형식 카드 "PLY". 크기: 일반적으로 100 %(기준값). 호환 대상: SuperSplat, PolyCam, 모든 3DGS 뷰어.
기술적 설명
PLY는 3D 가우시안 스플래팅의 정본 저장 형식이다. RadianceKit은 표준화된 3DGS 속성 레이아웃을 갖는 바이너리 리틀 엔디언 파일을 기록한다. 가우시안마다 3성분 위치, 항상 0으로 설정되는 세 개의 노멀, DC-SH 계수 세 개(f_dc_0..2, 기본 RGB 색상용), 이어서 Kerbl-2023 논문에서 정의된 전치된 채널-메이저 배열(먼저 모든 R 채널 계수, 그다음 모든 G, 그다음 모든 B)의 최대 45개 추가 SH 계수(f_rest_0..44), 그 뒤에 로짓 불투명도(원시 pre-sigmoid 값), 로그 공간 스케일 세 개, wxyz 쿼터니언 회전이 이어진다. 내보내지는 최대 SH 차수는 사용자 요청과 실제로 학습된 차수 중 최소값으로 클램프되며, 기본값은 3이다(45개의 나머지 계수). 기록 전에 극단적으로 큰 클라우드에서의 오버플로를 잡기 위해 페이로드 크기는 64비트 정수로 계산된다. 파일은 원자적으로 기록되며, 큰 클라우드의 경우 일시적으로 디스크 공간을 두 배 차지한다.
E2 — Compressed PLY (.ply)
위치
메뉴 바 → Export → 3D Formats → Export Compressed PLY…. 심플 모드: 형식 카드 "Compressed PLY". 크기: PLY 대비 약 10~20 %(5~10배 압축). 호환 대상: SuperSplat, PlayCanvas 엔진, 웹 기반 뷰어.
기술적 설명
청크 단위 양자화를 사용하는 PLY 형식의 PlayCanvas 변형이다. 가우시안은 256개 단위 청크로 그룹화된다. 청크마다 위치, 스케일, 색상에 대한 최소/최대 경계값이 헤더에 별도로 저장되며, 개별 가우시안은 이 경계값을 기준으로 상대적인 값을 참조하고 각각 32비트로 압축된다: 위치와 스케일은 11-10-11 비트 패킹, 회전은 2-10-10-10 비트 "Smallest-Three" 쿼터니언, 색상은 8-8-8-8 RGBA로 표현된다. 상위 SH 계수는 계수와 가우시안당 3바이트씩 (성분당 8비트만으로) 양자화된다. 이 형식 자체는 여전히 ASCII 헤더 PLY이며 기본적으로 PLY 도구로 검증할 수 있지만, 정점 속성이 uint 필드로 선언되어 있다. SH 차수는 압축을 최대화하기 위해 기본값이 0(추가 계수 없음)이며 — 더 높은 SH 차수도 명시적으로 선택할 수 있다.
E3 — SPZ (.spz)
위치
메뉴 바 → Export → 3D Formats → Export SPZ…. 심플 모드: 형식 카드 "SPZ". 크기: PLY 대비 약 10 %(90 % 더 작음). 호환 대상: Niantic Scaniverse, Niantic Spatial Fields, MetalSplatter.
기술적 설명
Niantic의 SPZ v2 형식이다. 위치는 24비트 고정소수점으로 패킹되고(대략 0.25mm 해상도), 스케일은 로그 공간에서 8비트 양자화되며, 회전은 8비트 Smallest-Three로 표현된다(v2에서는 xyz만 저장되고 w는 디코더에서 쿼터니언 노름으로부터 유도된다). 불투명도는 시그모이드 처리된 8비트 값으로 저장된다. DC-SH는 SPZ 전용 패킹 공식(dc_raw * 0.15 * 255 + 0.5 * 255)으로 저장되며, 상위 SH 밴드는 계수당 5비트(밴드 1) 또는 4비트(밴드 2-3)로 저장된다. 전체 패킹된 바이너리 블롭은 이후 표준 gzip(RFC 1952)으로 압축되어 매직 바이트 1f 8b를 가진 gzip 컨테이너 형식이 된다. RadianceKit은 이를 위해 시스템 gzip을 호출하는데, Apple의 내장 zlib API가 Spatial Fields나 MetalSplatter의 SPZ 리더와 호환되지 않는 독점적인 Apple 프레이밍을 생성하기 때문이다. 시스템 gzip은 macOS 샌드박스 내에서도 spawn 가능하다.
E4 — SOG (.sog)
위치
메뉴 바 → Export → 3D Formats → Export SOG…. 심플 모드: 형식 카드 "SOG". 크기: PLY 대비 약 5~6 %(15~20배 압축 — 가장 작은 옵션). 호환 대상: PlayCanvas 엔진, SuperSplat 에디터.
기술적 설명
"Spatially Ordered Gaussians" — 클라우드를 GPU에 바로 사용할 수 있는 여러 개의 무손실 WebP 이미지로 저장하는 PlayCanvas 형식이다. 먼저 모든 가우시안이 3D 모튼 코드(30비트 Z-오더, 축당 10비트)로 공간 정렬되며, 이는 나중에 렌더러에서 캐시 지역성을 높여준다. 그다음 위치는 대칭 로그 변환(더 나은 동적 범위를 위해)으로 16비트 값으로 양자화되어 두 개의 RGBA 이미지로 분할된다(means_l.webp는 하위 8비트, means_u.webp는 상위 8비트용). 회전은 RGBA 이미지 하나 안에 3×8비트 플러스 2비트 모드를 갖는 Smallest-Three로 인코딩된다(모드는 알파 채널에 252 + largest로 저장). 스케일과 DC-SH는 각각 256개 항목의 코드북으로 양자화되며(모든 값에 대한 백분위수 기반 분포), 인덱스는 scales.webp와 sh0.webp에 저장된다. 이 다섯 개의 이미지와 코드북 및 경계값을 담은 meta.json이 ZIP 파일로 압축되어(샌드박스가 시스템 zip을 차단하기 때문에 커스텀 인코더 사용) .sog 확장자로 저장된다.
샌드박스 주의: SOG는 외부 바이너리가 필요한 유일한 형식 옵션이다. WebP 인코더 단계는 /usr/local/bin/cwebp 또는 /opt/homebrew/bin/cwebp의 cwebp를 호출한다. cwebp 바이너리를 찾지 못하면 코드는 원시 PNG 인코딩으로 폴백한다 — 하지만: PNG 폴백은 SuperSplat에서 작동하지 않는다. 앱스토어 버전에서는 빌드 변형에 따라 가용성을 평가한다. 개발자 버전에서는 Homebrew를 통해 cwebp를 설치해야 한다(brew install webp).
E5 — glTF (.glb)
위치
메뉴 바 → Export → 3D Formats → Export glTF…. 심플 모드: 형식 카드 "glTF". 크기: PLY와 유사. 호환 대상: KHR_gaussian_splatting 확장(Khronos 초안 표준)을 지원하는 glTF 뷰어.
기술적 설명
KHR_gaussian_splatting 확장 명세에 따라 자체 완결형 .glb 바이너리 파일(별도 bin 파일 첨부 없음)을 기록한다. 위치는 일반 glTF POSITION 정점 데이터(float3)로 저장되며, 다른 모든 속성(float4 회전, float3 스케일, float 불투명도, float3 × shCoeffCount SH 계수)은 추가 정점 속성에 저장되고 확장을 통해 참조된다. 중요한 점: glTF는 오른손 좌표계 Y-up을 사용하지만, COLMAP/3DGS는 Y-down/Z-forward로 작업한다. 그래서 익스포터는 X축 기준 180도 회전을 적용한다 — 위치는 (x, -y, -z)로 다시 기록되고, 쿼터니언은 (w, x, -y, -z)로 조정된다. 이렇게 하면 glTF 뷰어에서 기하학적으로 올바르고(거울상이 아닌) 손대칭이 정확한 표현이 된다. JSON 청크와 바이너리 청크는 GLB 표준이 요구하는 대로 4바이트 정렬로 패딩된다.
E6 — Splat (.splat)
위치
메뉴 바 → Export → 3D Formats → Export .splat…. 심플 모드: 형식 카드 ".splat". 크기: 가우시안당 정확히 32바이트. 호환 대상: gsplat.js, 웹 기반 뷰어(antimatter15 레퍼런스), 대부분의 브라우저 3DGS 데모.
기술적 설명
antimatter15의 .splat 형식 — 가우시안당 32바이트, 헤더 없음, 간접 참조 없음. 항목당 레이아웃: 3 × float32 위치(월드 좌표), 3 × float32 스케일(내부 버퍼의 로그 공간에서 exp 변환됨), 4 × uint8 RGBA 색상(SH_C0 = 0.282...로 스케일되고 [0,255]로 클램프된 DC-SH 계수), 4 × uint8 쿼터니언(w,x,y,z, 정규화되어 128 + 128*q로 바이트 범위에 인코딩됨). DC-SH만 저장되며 — 상위 SH 밴드는 버려진다. 이는 형식을 극도로 압축적으로 만들지만, 반사나 스펙큘러 하이라이트에서 나타나는 시점 의존적 색상 변화를 잃는 대가를 치른다. 기록 순서는 클라우드의 인덱스 순서 그대로이며 (공간 정렬 없음), gsplat.js 같은 웹 뷰어는 이를 전제로 렌더링한다.

flowers-01.html을 Finder에서 더블클릭해 기본 브라우저에서 바로 열었다 — 내장된 WebGL2 프로그램이 네트워크나 서버 없이 가우시안 클라우드를 즉시 렌더링한다. 부케 주변의 검은 마커는 학습에 사용된 카메라들로, 선택적으로 표시할 수 있다. 마우스 드래그로 회전하고 스크롤로 확대/축소한다.E7 — Web Viewer (.html)
위치
메뉴 바 → Export → Media → Export Web Viewer…. 심플 모드: 형식 카드 "Web Viewer". 크기: Base64로 인코딩된 스플랫 데이터(약 4/3 오버헤드) + 약 5 KB의 HTML/JS 셸. 호환 대상: WebGL2를 지원하는 모든 최신 브라우저(모든 데스크톱, iOS 15+, Android 5+).
기술적 설명
가우시안 클라우드를 완전히 인라인으로 작성된 WebGL2 렌더러와 함께 단일 .html 파일로 묶는다. CDN 의존성도, WASM도, 두 번째 파일도 없다. 클라우드는 내부적으로 먼저 .splat 바이너리로 인코딩되고(E6과 동일한 32바이트 로직), 그다음 base64로 임베드되어 브라우저에서 atob로 디코딩된다. 내장된 렌더러는 자체 WebGL2 정렬, 마우스 오빗 조작, 프레임별 CPU 정렬을 수행한다. 전체 JS 코드(셰이더, 수학, 루프)는 결과 HTML에서 그대로 볼 수 있다. 저장소-렌더러 경계의 축 규약은 E5와 정확히 동일하다: 위치 (x, -y, -z), 쿼터니언 (w, x, -y, -z). 선택적으로 브랜딩 오버레이를 표시할 수 있다(무료 등급 스위치). 모든 것이 인라인이므로, 파일은 file:// 프로토콜에서도 직접 작동한다 — 테스트를 위한 로컬 웹서버가 필요 없다.

E8 — Orbit Video (.mp4/.mov)
위치
메뉴 바 → Viewport → Record Turntable Video 또는 메뉴 바 → Export → Media → Export Orbit Video…. 심플 모드: 형식 카드 "Orbit Video"에 3~30초 지속 시간 슬라이더가 있음. 크기: 지속 시간, 해상도, 비트레이트에 따라 다름. 호환 대상: 모든 플랫폼(H.264와 HEVC는 Apple 표준).
기술적 설명
가우시안 클라우드를 파라메트릭 오빗 카메라 이동을 따라 렌더링하고, 각 프레임을 AVAssetWriter를 통해 MP4 또는 MOV 파일로 인코딩한다. 오빗 설정은 회전 속도(회전 수), 거리, 고도, FOV, 지속 시간, 이즈인/아웃 계수를 제어한다. Orbit Video 내보내기는 RadianceKit 자체의 완전한 SH 평가를 사용하는 렌더링 단계를 거친다 — 앱 내 뷰포트와 픽셀 단위로 동일하다(WYSIWYG). 프레임마다 월드 정렬 행렬(렌더러가 내부 좌표를 Y-up 오빗 월드로 회전시키기 위해 계산함)이 카메라와 곱해지고, 이어서 카메라 변환 미러링 (오빗 Y-up → COLMAP Y-down)이 적용된다. 오프스크린 렌더 타겟은 IOSurface를 통해 인코더용 CVPixelBuffer로 전달된다. 인코더는 H.264와 HEVC를 지원하며 비트레이트와 해상도(480p~8K)를 설정할 수 있다. 첫 프레임 전에 렌더러는 초기 스플랫 정렬이 완료될 때까지 200ms를 대기한다. 이 내보내기는 GPU 바운드다 — 8K와 수백만 개의 가우시안에서는 프레임당 렌더링 시간이 몇 초에 달하므로, 6초 분량의 비디오에도 총 렌더링 시간이 10~30분에 이를 수 있다.
E9 — SfM Transforms (transforms.json)
위치
메뉴 바 → Export → Photogrammetry → Export SfM (transforms.json)…. 크기: 일반적으로 1~10 KB(포즈와 내부 파라미터만, 이미지나 가우시안 없음). 호환 대상: nerfstudio, Brush, gsplat, OpenSplat, Meshroom, 모든 최신 피드포워드 3DGS 트레이너.
기술적 설명
카메라 포즈 목록과 공유된 내부 파라미터를 담은 nerfstudio transforms.json 형식을 기록한다. 카메라마다 뷰 행렬 (RadianceKit 내부: COLMAP 규약의 World-to-Camera)이 역행렬로 변환되고, 이어서 카메라 로컬 Y축과 Z축 기저 벡터가 미러링되어 nerfstudio 규약(OpenGL 스타일, 카메라가 -Z를 따라 바라보고 +Y가 위쪽)으로 변환된다. 최종 4×4 행렬은 각 프레임의 transform_matrix 필드에 row-major 중첩 배열의 double 값으로 저장된다. 내부 파라미터는 최상위 레벨에 저장된다(초점 거리 x/y, 주점 x/y, 이미지 너비/높이, camera_model = "OPENCV", 왜곡 계수 k1, k2, p1, p2) — 단, 익스포터가 여러 개의 서로 다른 내부 파라미터 세트를 감지하면 프레임별로 기록한다. 이미지 경로는 JSON 파일 기준 상대 경로인 images/<filename>으로 기록된다. 사용자는 학습용 사진이 들어 있는 형제 images/ 폴더를 만들어야 한다.
E10 — COLMAP Workspace (sparse/0/)
위치
메뉴 바 → Export → Photogrammetry → Export SfM (COLMAP Workspace)…. 크기: 세 개의 바이너리 파일을 합쳐 일반적으로 4~8 MB — points3D.bin이 지배적이다(스파스 클라우드의 3D 점마다 한 줄), images.bin과 cameras.bin은 각각 100 KB 이하이다. 호환 대상: COLMAP 자체, Nerfstudio, Postshot, Meshroom, COLMAP sparse/ 디렉터리를 기대하는 모든 도구.
기술적 설명
세 개의 바이너리 파일로 구성된 표준 COLMAP sparse/0/ 레이아웃을 기록한다: cameras.bin, images.bin, points3D.bin. 형식 참조는 공식 COLMAP 문서다. cameras.bin에는 중복 제거된 내부 파라미터 목록이 들어 있다(동일한 내부 파라미터와 이미지 크기를 가진 카메라는 하나의 항목으로 병합됨). 사용되는 카메라 모델은 OPENCV(모델 4)이며, fx/fy/cx/cy와 네 개의 왜곡 계수 k1/k2/p1/p2를 포함한다. images.bin은 이미지마다 wxyz 쿼터니언과 이동 벡터로 포즈를 나열하고, 그다음 카메라 ID와 파일명이 이어진다. 2D-3D 대응 관계는 저장되지 않는다. points3D.bin에는 위치, 색상(0~255 RGB), 재투영 및 트랙 길이에 대한 기본값을 포함한 SfM 점군이 들어 있다. 모든 데이터는 리틀 엔디언으로 기록된다. RadianceKit으로의 재임포트는 File 메뉴 → "Import COLMAP/Metashape Workspace…"를 통해 이루어진다 (SfM 백엔드 장의 Q3 참조).
언제 어떤 포맷을?
| 목적 | 포맷 |
|---|---|
| 자체 사이트용 웹 뷰어 | E7 Web Viewer (.html) |
gsplat.js를 사용하는 웹 뷰어 | E6 Splat (.splat) |
| Postshot / Nerfstudio에서 파이프라인 재사용 | E9 transforms.json + E10 COLMAP Workspace |
| SuperSplat 편집 | E1 PLY 또는 E2 Compressed PLY |
| Niantic Scaniverse / Spatial Fields | E3 SPZ |
| 최대 압축 | E4 SOG (cwebp 필요) |
| 마케팅/소셜 영상 | E8 Orbit Video |
| 웹에서 씬 이어서 편집 | 포맷 그리드 아래에 있는 「Upload to SuperSplat…」 버튼 |
빠른 비교
| 형식 | 확장자 | 샌드박스 | 크기 (1M Gauss) | 최적 용도 |
|---|---|---|---|---|
| E1 PLY | .ply | 예 | ~250 MB | 아카이브, 최고 호환성 |
| E2 Compressed PLY | .ply | 예 | ~40 MB | 웹 + SuperSplat |
| E3 SPZ | .spz | 예 (gzip-Spawn) | ~40 MB | Niantic + 모바일 |
| E4 SOG | .sog | 조건부 (cwebp) | ~20 MB | 최대 압축 |
| E5 glTF | .glb | 예 | ~250 MB | Khronos 파이프라인 |
| E6 Splat | .splat | 예 | ~32 MB | gsplat.js 웹 뷰어 |
| E7 Web Viewer | .html | 예 | ~45 MB | 독립형 브라우저 파일 |
| E8 Orbit Video | .mp4/.mov | 예 | 가변적 | 소셜/마케팅 |
| E9 SfM Transforms | .json | 예 | ~5 KB | 포즈 전달 |
| E10 COLMAP Workspace | 디렉터리 | 예 | ~4–8 MB | 포즈 전달 바이너리 |
크기 열은 SH 등급 3의 1백만 Gaussians 기준 대략적인 참고값입니다. 실제 값은 장면의 압축 가능성에 따라 달라지며, SH 등급 0은 PLY/glTF 크기를 4배 줄입니다.