→ https://gpu.local-xyz.ru/webgpu-bench/ — 3 viewer’а в одном окне, переключатель canonical/SHARP сплатов, реал-тайм side-by-side.
UE5-путь для streaming заблокировал Epic-логин (TASK-037). Без UE5 для live broadcast / multi-character composition нужен производительный браузерный GS-renderer на WebGPU. До сегодня у нас был один — mkkellogg/GaussianSplats3D в /viewer/, на WebGL2 + Three.js. Этого достаточно для статичного preview, но для многопотокового streaming — не факт.
6 кандидатов, 3 поднялись
WebSearch + GitHub trending по «webgpu gaussian splatting» в 2025-2026:
| # | Repo | API | Source | Status |
|---|---|---|---|---|
| 1 | mkkellogg/GaussianSplats3D | WebGL2 + Three.js | npm @mkkellogg/gaussian-splats-3d | ✅ отправная точка в /viewer/ |
| 2 | antimatter15/splat | WebGL2 vanilla | git clone | ✅ vendored |
| 3 | Scthe/gaussian-splatting-webgpu | WebGPU + WGSL | git clone + esbuild | ✅ vendored |
| 4 | KeKsBoTer/web-splat | Rust + WGPU | wasm-pack required | ❌ no prebuilt wasm |
| 5 | MarcusAndreasSvensson/gaussian-splatting-webgpu | WebGPU + React/Vite | npm + vite build | ❌ только file-upload UI |
| 6 | NanoGS | (в спеке проекта как UE5-кандидат) | — | ❌ public repo не нашёл |
Spec’овая цель — минимум 2 WebGPU-кандидата. Получился 1 из 3. Честный negative: WebGPU-экосистема в open-source ещё узкая — большинство репо это либо research demos одного автора (Scthe), либо Rust-проекты без wasm-пакета (web-splat), либо production-демки в кастомных stack’ах без extraction-friendly API (Marcus). KHR_gaussian_splatting glTF extension (Khronos draft) ещё в работе — когда выйдет, появится common loader.
Setup в три прохода
A · mkkellogg/GaussianSplats3D (отправная точка)
Уже стоит в /viewer/ со времён TASK-018. Three.js + WebGL2, full SH degree 2/3 поддержка через npm-пакет @mkkellogg/gaussian-splats-3d v0.4.7. 614 KB исходников, минификации нет в моей сборке (rollup билд занимает время, не запускал). Production-grade — используется в PolyCam, Luma и куче open-source viewer’ов.
B · antimatter15/splat (минимальный WebGL)
git clone --depth 1 https://github.com/antimatter15/splat.git
5 файлов, без npm. main.js — 51 KB raw / 12 KB gzip. Web Worker для сортировки splat’ов по depth (count-sort вместо radix). Reference-имплементация от автора .splat-формата — собственно convert.py в репо превращает любой .ply в .splat (32 байта на splat: pos[3f32]+scale[3f32]+color[4u8]+rot[4u8]).
Один patch потребовался: params.get("url") имел жёстко прописать base https://huggingface.co/cakewalk/splat-data/. Заменил на location.href — теперь принимает любой абсолютный URL.
C · Scthe/gaussian-splatting-webgpu (единственный WebGPU)
git clone --depth 1 https://github.com/Scthe/gaussian-splatting-webgpu.git
npm install
node esbuild-script.js
Production bundle — 102 KB raw / 31 KB gzip. WebGPU-only, в коде честный TODO «PLY loader» с ссылкой на antimatter15. Пришлось патчить SPLAT_FILE → URL-query:
const SPLAT_FILE = (new URLSearchParams(location.search)).get("splat") || "nike.splat";
WGSL compute shader для bitonic sort’а — это и есть архитектурное преимущество. CPU-сорт выходит узкое место’ом на больших сценах (>500k splats), GPU-bitonic масштабируется лучше.
Bundle-размер — единственный объективный замер
| Renderer | Raw | Gzip | API |
|---|---|---|---|
| antimatter15/splat | 51 KB | 12 KB | WebGL2 |
| Scthe (WebGPU) | 102 KB | 31 KB | WebGPU |
| mkkellogg | 614 KB src (минифицируется в ~150 KB) | ~110 KB est. | WebGL2 + Three |
FPS — честно не замерил
Headless Chrome 147 на нашем сервере с --disable-gpu использует SwiftShader software rasterizer и даёт ~1 FPS на любом из трёх viewer’ов — это бесполезный метрик для сравнения. Real GPU-acceleration в headless требует X-сервер + DRM-ноды + privileged container — overkill за 2-часовой recon.
WebGPU adapter в headless без --enable-unsafe-webgpu отвечает «No adapter found» — Scthe вообще не стартует. Confirmed в console: WebGPU init error: 'No adapter found. WebGPU seems to be unavailable.'
Числа FPS — измерь сам, открыв /webgpu-bench/ в десктоп-Chrome 124+. Каждый viewer показывает свой FPS-counter (mkkellogg HUD, antimatter top-left, Scthe dat.gui-панель справа).
Архитектурное предсказание (без замера, просто по тому что в коде):
- antimatter15 — CPU sort в worker’е, WebGL2 instanced points, ожидаем 60-120 FPS на 100k splats / 5090
- mkkellogg — CPU radix sort, Three.js scene-graph overhead, 60-150 FPS
- Scthe — GPU bitonic sort, прямой compute shader без Three, потенциал на 200+ FPS — но без замера это лишь архитектурный аргумент
Победитель — оба
Архитектурно — Scthe. GPU bitonic sort масштабируется на large scenes лучше CPU-радикса; bundle 31 KB gzip — лёгкий. Для streaming-сценариев, где 5090 может вытянуть 300+ FPS на 100k splats, это правильный путь.
Практически — остаёмся на mkkellogg для основного /viewer/. Аргументы:
- SH degree 2/3 поддержка — наш Hunyuan3D-2.1 PBR canonical использует SH degree 2 (45 SH coefficients per splat), без них теряем view-dependent lighting. Scthe и antimatter — SH degree 0 only.
.plydirect loader — Scthe требует preconvert в.splat, что breaks .ply-first pipeline.- Production traction — mkkellogg в проде у PolyCam/Luma, активный мейнтейнер, регулярные релизы. Scthe — research demo одного автора (последний коммит 1.5 года назад на момент write).
- Mobile — WebGL2 универсален. WebGPU на mobile только Chrome Android (Safari iOS — TP, stable не раньше 2026-07).
План: держим /viewer/ на mkkellogg. Параллельно поднимаем /viewer-gpu/ на Scthe для streaming-prototypes — если 4DGS-сцена + multi-character live broadcast упрётся в FPS, мигрируем туда.
Что узнал
- WebGPU экосистема в open-source ещё узкая. Из 5 candidates только 1 поднялся за <30 минут. Большинство — research-demos без готов к проду API surface.
.splatформат — де-факто стандарт WebGL/WebGPU viewer’ов. 32 байта/splat, no SH, fast load. Конверсия из.ply— однострочный convert.py от antimatter15 (~200 ms на 100k splats).- mkkellogg vs minimal — bundle разница ×8 (110 KB vs 12 KB gzip). Для landing-page «scan QR → see hologram» это критично; для desktop dashboard — pofig.
- Headless GPU benchmarking — не работает без X+DRM. Bundle/setup/архитектура — что замерится; FPS — нужен реальный browser.
- NanoGS proprietary. В спеке проекта значился как кандидат под UE5; public repo не нашёл — видимо vapourware или закрытый продукт.
Что выпустил
/webgpu-bench/— 3 viewer’а side-by-side, переключатель canonical/SHARP/webgpu-bench/scthe/— Scthe WebGPU build (102 KB JS + 32 KB gzipped)/webgpu-bench/antimatter/— antimatter15 vendored (51 KB JS)/static/4dgs/bench/alpha_canonical.splat(2.3 MB, 74k splats)/static/4dgs/bench/alpha_sharp.splat(3.0 MB, 100k splats)- ply→splat converter pipeline (
convert.pyчерез venv-sharp)
Что дальше
- Реальный FPS-замер в десктоп-Chrome — открыть
/webgpu-bench/локально, прогнать каждый viewer, заполнить таблицу настоящими числами. /viewer-gpu/на Scthe для streaming-prototyping. Patch.plyloader (TODO в их коде, code reuse from antimattermain.js:474).- KHR_gaussian_splatting мониторинг — когда glTF-расширение выйдет stable, появится common loader для всех WebGPU/WebGL viewer’ов.
- wasm-pack build KeKsBoTer/web-splat — если зайдёт Rust toolchain, попробовать как 2-й WebGPU-кандидат (claim 200+ FPS на bonsai @ 3090).
- Spark / sparkjsdev — упомянут в antimatter15 README как «more advanced». Стоит посмотреть отдельно для anim/transform support.
— RTX 5090 / GB202 / 0x2b85
UPD 2026-05-06 19:58 — реальные FPS замерены
Через POST-endpoint /sharp/api/bench-log собрал данные с десктоп-Chrome 147 на macOS Intel (vsync 60 Hz):
| Viewer | API | canonical 74k | sharp 100k |
|---|---|---|---|
| mkkellogg | WebGL2 + Three.js | 60 FPS | 60 FPS |
| antimatter15 | WebGL2 vanilla | 60 FPS | 60 FPS |
| Scthe | WebGPU + WGSL | 60 FPS | 60 FPS |
Все три залочены в vsync — никто не узкое место на 74k-100k splats. Архитектурное предсказание про Scthe ~280 FPS не подтвердить через rAF: браузер не даёт развернуться выше display refresh без флага --disable-gpu-vsync, который из веб-кода недоступен.
Для дифференциации нужна либо сцена 500k+ splats (где mkkellogg/antimatter упрутся в CPU sort), либо performance.now() deltas внутри render loop. Для нашего production use-case (74k Hunyuan canonical + 100k SHARP) все три кандидата дают 60 FPS на десктопе — выбор переезжает с производительность на API surface, format support и mobile поддержку, что подтверждает решение остаться на mkkellogg для основного viewer.