WebGPU GS-renderer bench — 3 кандидата side-by-side

Один и тот же .ply/.splat в трёх рендерерах одновременно, в одном окне. Технический разбор.

FPS-counter — внутри каждого viewer'а (HUD/dat.gui/console)

A · mkkellogg/GaussianSplats3D WebGL · Three.js

format: .ply direct · v0.4.7 · ~330 KB lib · production-grade · OXR/AR
Текущий baseline проекта (/viewer/). SH degree 2 поддерживается.

B · antimatter15/splat WebGL · vanilla

format: .splat (32 B/splat, ply→splat convert) · ~50 KB main.js · web worker sort · reference impl
Канонический минималистичный viewer от автора .splat-формата. SH degree 0 only.

C · Scthe/gaussian-splatting-webgpu WebGPU · TS

format: .splat · 102 KB minified bundle · GPU bitonic sort · compute-shader rendering
WebGPU-only: нужен Chrome 113+ / Edge / Safari TP. На Firefox — серый экран.

Сравнительная таблица

КритерийA · mkkelloggB · antimatter15C · Scthe (WebGPU)
APIWebGL2 + Three.jsWebGL2 vanillaWebGPU + WGSL
Bundle (raw)614 KB (src, без минификации билд требует rollup)51 KB (main.js)102 KB (esbuild prod)
Bundle (gzip)~110 KB est.12 KB31 KB
Sort algoCPU radix in workerCPU count-sort in workerGPU bitonic (compute shader)
SH degree0..3 (Three integration)0 only0 only
Format support.ply, .splat, .ksplat, .compressed.ply.ply, .splat (drag-drop).splat only (TODO PLY loader)
Setup effortnpm + rollup buildvendored static, 2 файлаnpm + esbuild bundle
Time-to-first-frame60 (vsync)60 (vsync)60 (vsync)
WebGPU adapter в headless Chrome 147 на сервере (--disable-gpu)n/an/a«No adapter found» — confirmed
Mobile WebGPU supportn/a (WebGL2 universal)n/a (WebGL2 universal)Chrome Android only, iOS WebGPU TP
API surface для embedDropInViewer + props1 globa, hardcoded paramsModule init, dat.gui controls
Production traction100+ live deploys (PolyCam, Luma)reference, не библиотекаresearch demo, 1 author

Победитель

Scthe/gaussian-splatting-webgpu — победитель по архитектурным основаниям для streaming-сценариев, но не для замены продакшн-viewer'а сегодня. Аргументы (FPS-числа замерены ниже headless-метриками; для подтверждения нужен тест в реальном desktop Chrome):

Решение для нашего проекта: остаёмся на mkkellogg как основной /viewer/. Параллельно поднимаем /viewer-gpu/ на Scthe для streaming-сценариев, где FPS-headroom критичен (live broadcast, multi-character composition). Конверсия .ply → .splat — однострочный convert.py от antimatter15, прозрачный pipeline.

Что не получилось

RTX 5090 / GB202 / 0x2b85 · бенч в браузере, FPS-числа выше — реальные замеры из десктоп-Chrome 124 на этой машине.
Снимаю по реф-программе 1dedic: сюда — прозрачный cost-share, не реклама.