This tool was created by Epic Games Slovakia, who doesn't carry any liability in case issues related to the sample occur.
© 2026 Epic Games, Inc. RealityScan® is a trademark of Epic Games, Inc. This tool is provided under the RealityScan End User License Agreement: https://www.realityscan.com/eula
Browser-based converter from 360 equirectangular panoramas — or 360 video frames — to flat cube faces.
Drop a 2:1 equirectangular JPG/PNG (from any 360 camera — Insta360, GoPro Max, Ricoh Theta, etc.), or an equirect MP4/MOV video — or a whole folder of either — pick a field of view, click Convert. The faces come out as a ZIP, with the original folder structure preserved. Everything runs in the user's browser; no media are uploaded anywhere.
- Drop folders, images, or videos — drag any combination onto the page, or use "Choose folder" to pick one. Subfolders are walked recursively.
- Video frame extraction — drop a 360 MP4/MOV and the tool pulls a frame every N seconds (configurable), then converts each frame to a cubemap. Already-stitched equirect videos only; raw
.insv/.360files aren't supported. - FOV slider — 60–120°, default 90°. 90° = standard cubemap (faces tile exactly). Higher = overlap (useful for photogrammetry). Lower = gaps.
- Match source resolution by default — preserves the original pixel detail (e.g. 11968×5984 equirect → ~3000 px per face). Or pick a fixed size.
- Auto-batching for huge jobs — long videos or massive folders are automatically split into multiple ~800 MB ZIPs so the browser tab doesn't run out of memory.
- Privacy: WebGL processes images and video locally on the user's GPU. Pull the network cable after page load and it still works.
A WebGL2 fragment shader does the per-pixel work: for each output pixel, compute the camera-space ray from the FOV, rotate by the per-face yaw/pitch, convert to spherical coordinates, sample the equirect texture with bilinear filtering. JSZip packages the rendered faces into a download.
The conversion is a standard equirectangular-to-perspective projection applied once per cube face.
Images flatten into their source folder — six face JPEGs per image, sitting next to siblings:
pano2views_cubemap_fov90.zip
└── <original-folder-path>/
├── <image-stem>_front.jpg
├── <image-stem>_right.jpg
├── <image-stem>_back.jpg
├── <image-stem>_left.jpg
├── <image-stem>_up.jpg
└── <image-stem>_down.jpg
Videos get one folder of their own (many frame-faces would otherwise crowd out sibling images). Timestamps are zero-padded so they sort cleanly:
pano2views_cubemap_fov90.zip
└── <original-folder-path>/
└── <video-stem>/
├── <video-stem>_t00000.00s_front.jpg
├── <video-stem>_t00000.00s_right.jpg
├── ...
├── <video-stem>_t00002.00s_front.jpg
└── ...
If you drop loose files (no folder), <original-folder-path> is omitted — output sits at the ZIP root.
If Write RealityScan XMP sidecars is ticked (default), each .jpg ships with a matching .xmp carrying fixed calibration — focal derived from the FOV slider, principal point (0, 0), square aspect, no distortion, CalibrationPrior="exact". RealityScan reads the XMP on import and skips re-solving the intrinsics; no pose is written, so alignment is still free.
index.html UI + styles
layouts.js face yaw/pitch tables (extensible — add more layouts here)
shaders.js GLSL vertex + fragment source
render.js WebGL2 setup, texture upload, per-face draw
app.js drag-drop, folder walk, FOV slider, ZIP packaging
No build step, no npm, no framework.
cd pano2views
python -m http.server 8000
Open http://localhost:8000 in any modern browser. (file:// won't work — image decoding has cross-origin restrictions.)
GitHub Pages from the repo root, main branch. After pushing, go to Settings → Pages → set Source = "Deploy from branch" / Branch = main / (root). Site is live in ~30 seconds at https://<username>.github.io/pano2views/.
While the repo is private, the published URL is still publicly reachable but unindexed — anyone with the URL can use the tool. Repo + Pages access control behind GitHub login requires a GitHub Enterprise Cloud plan.
Anything with WebGL2 (Chrome 56+, Firefox 51+, Edge 79+, Safari 15+) — ~96% of installed browsers.
Mobile works but is capped by the device's MAX_TEXTURE_SIZE (typically 4096–8192). Insta360 X3 11968×5984 equirects exceed that on most phones — use desktop for max-resolution sources.
Append to LAYOUTS in layouts.js:
LAYOUTS.myLayout = {
label: "My layout",
description: "Short description for the UI.",
defaultFov: 100,
faces: [
{ name: "v1", yaw: 0, pitch: 0 },
// ...
],
};Re-add a layout dropdown to index.html to expose it (currently hidden for the cubemap-only MVP).