A complete port of Apple's SHARP (single-image 3D Gaussian Splat generation) from PyTorch to WebGPU compute shaders. No server, no WASM, no ONNX runtime — pure GPU compute shaders dispatched from JavaScript.
Drop an image in the browser and get 1.18 million 3D Gaussian Splats in ~25 seconds on Apple M4 Max. Download as a standard .ply file compatible with any 3DGS viewer.
| Input | Output (1.18M Gaussian Splats) |
|---|---|
![]() |
![]() |
| Component | Status |
|---|---|
| ViT-Large backbone (DINOv2, patch_size=16) | Working (~480ms per patch) |
| SPN encoder (35 batched ViT passes) | Working (~18s) |
| Monodepth decoder (depth map) | Working |
| Gaussian decoder (texture + geometry features) | Working |
| Prediction head (14-channel deltas) | Working |
| Initializer + Composer (base + deltas → 3DGS) | Working |
| PLY export | Working (1.18M splats, ~66 MB) |
| Weight conversion (PyTorch → flat binary) | Working (702M params, 1.25 GB fp16) |
SHARP predicts 3D Gaussian Splats from a single image in a single feedforward pass:
Image (1536x1536)
→ SlidingPyramidNetwork
→ 3-level pyramid (1536 → 768 → 384)
→ 35 overlapping patches (5x5 + 3x3 + 1x1) through DINOv2 ViT-Large
→ overlap merge + upsample fusion → 5 multi-resolution feature maps
→ MonodepthDPT (MultiresConvDecoder + disparity head → depth map)
→ GaussianDecoder DPT (MultiresConvDecoder + SkipConvBackbone → features)
→ DirectPredictionHead (14-channel deltas per Gaussian layer)
→ MultiLayerInitializer (base Gaussians from image + depth)
→ GaussianComposer (base + deltas → 1.18M 3D Gaussian Splats)
→ PLY export (standard 3DGS format)
14 WGSL compute shaders handle all operations: patch embedding, layer norm, multi-head self-attention, linear projection, GELU MLP, layer scale, conv2d, conv1x1, conv_transpose2d, bilinear upsample, pixel shuffle, group norm, and activations (ReLU, SiLU, sigmoid, softplus).
git clone https://github.com/lyonsno/sharp-webgpu.git
cd sharp-webgpu
npm installRequires a Python environment with PyTorch. The converter downloads the default SHARP checkpoint from Apple's CDN (~2.7 GB PyTorch, converts to ~1.25 GB fp16 binary):
# If you have ml-sharp's venv:
path/to/python tools/convert_weights.py --output public/weights.bin --dtype fp16
# Or install torch separately:
pip install torch
python tools/convert_weights.py --output public/weights.bin --dtype fp16To just inspect the tensor list without downloading:
python tools/convert_weights.py --list-onlynpm run dev
# Open http://localhost:5175/Check "Run full SPN", click a sample image or drop your own. After ~25 seconds you'll see a depth map and a download link for the .ply file containing 1.18M Gaussian Splats.
The .ply file loads in any standard 3DGS viewer (SuperSplat, Kaminos, etc.).
- Chrome 113+ or Edge 113+ (WebGPU enabled)
- Firefox 141+ (WebGPU enabled via
dom.webgpu.enabledin about:config) - GPU with WebGPU support
On Apple M4 Max (128 GB):
| Stage | Time |
|---|---|
| Weight loading (first run) | ~5s |
| SPN encoder (35 ViT passes) | ~18s |
| Monodepth decoder | ~2s |
| Gaussian decoder + compose | ~3s |
| Total | ~25s |
~90% of the ViT compute shaders are shared with moge-webgpu (MoGe-2 depth estimation in WebGPU). Both models use DINOv2 ViT-Large backbones — SHARP uses patch_size=16 (vs MoGe's 14), but the attention, layernorm, linear, and MLP shaders are identical.
tools/convert_weights.py— Convert SHARP PyTorch checkpoint to WebGPU binary formattools/dump_reference.py— Dump PyTorch fp16 reference intermediates at 25 pipeline stages for parity comparisontools/parity_compare.mjs— Compare WebGPU PLY output against reference dumps (per-field maxErr/rmsErr/relStd)tools/witness.mjs— Automated inference witness (headless Chrome + WebGPU)tools/backbone_smoke.mjs— Backbone-only smoke testtools/demo_smoke.mjs— Demo UI smoke test
Run the reference model in fp16 on MPS and dump intermediates:
python tools/dump_reference.py --image public/samples/sample_1.jpg --output public/reference_dumps/ --dtype fp16Then compare WebGPU output against the reference (requires vite dev server running):
node tools/parity_compare.mjs --port 5175 --manifest public/reference_dumps/manifest.jsonThe comparator extracts the PLY from the browser pipeline and reports per-field error statistics against the reference. The compareArrays function and reporting format are reusable across models (MoGe, SF3D, Kimodo).
This port is provided under the same terms as Apple's original:
- Code: Apple License (use, reproduce, modify, redistribute with attribution)
- Model weights: Apple ML Research Model License (non-commercial research only)
The WGSL compute shaders and JavaScript inference code in this repository are original work.
- SHARP: Sharp Monocular View Synthesis in Less Than a Second — Mescheder et al., Apple Research
- apple/ml-sharp — Original PyTorch implementation
- arXiv:2512.10685 — Paper

