Walk-in gaussian splats: the "View in 3D" mode on my photography portfolio (PlayCanvas engine)

Hi all - I’m a landscape photographer and ML engineer. I wanted my photos to keep some of the depth the scene actually had, so I built a pipeline that turns each photograph into a gaussian splat you can look around inside, and wired it into my portfolio’s lightbox as a “View in 3D” button.

Live: John Muir Trail Photo Diary — 211 Miles in the Sierra Nevada | Danil Zanozin Photography — open a photo, hit “View in 3D.” (Desktop only for now - more on that below.)

The part I think is interesting: the splat comes from the photograph itself, not a multi-view capture. The pipeline:

  • Apple’s SHARP (monocular image → 3D gaussian splats) runs on the full-size JPEG
  • Raw splats get 50% pairwise-merge decimation and compress to .sog (~6 MB per photo) via @playcanvas/splat-transform - that package saved me weeks, thanks to whoever maintains it
  • The viewer runs on the PlayCanvas engine (2.11), with the camera initialized at the photo’s capture FOV so the splat aligns 1:1 with the flat image before you start moving - the transition from “photo” to “space” is the whole magic trick
  • Gallery hover gets a cheaper effect: the same pipeline rasterizes a 768×768 depth map per photo (~60–110 KB), and a single shared WebGL canvas does depth-displaced parallax on whichever tile you’re over - no per-tile contexts
  • Fully automated and incremental: one Python command processes only photos missing their 3D assets, so a new gallery costs nothing

It’s currently running across my whole portfolio (a couple hundred photos, ~1.1 GB of .sog).

Two things I’d genuinely love input on:

  1. Mobile. The splat viewer is desktop-only right now. If you’ve shipped splats on mobile browsers - what made it viable? Aggressive decimation, lower splat counts, a different renderer path?
  2. Asset size. 6 MB per view is my biggest UX cost. Anyone found a good progressive-loading or LOD story for .sog?

Happy to go deeper on any part of the pipeline if people are curious.

1 Like

Hey @Danil
Well done!

1 Like

This is well done, really love it. Great insight of matching the FOV of photo for initial view!

I don’t like the mouse over interaction, the part when the mouse pops out of being over the photo, the direction reverts.

Regarding LOD - we do support streamed-sog, you could generate 2-3 levels for each photo using decimation, then loading to first interactive rendering would be much quicker. But I have not tested this with SHARP based content, the overhead might be too large here.