canvas

video / panorama / equirectangular

What this shows

An animated equirectangular panorama is mapped onto the inside of an inverted sphere; drag to look around from its centre.

Side by side with the three.js r186 original: webgl_video_panorama_equirectangular.html

Differences from three.js

  • textures/pano.webm and pano.mp4 carry no licence notice, so both sides substitute a generated 512x256 equirectangular canvas animation (sky, ground, a circling sun and pillars every 30 degrees) drawn each frame and used as a CanvasTexture instead of a VideoTexture.
  • EASEL caches the panorama at 128x128 and samples it nearest-neighbor with affine warping, so the surroundings are blocky and bend across the 60x40 sphere's faces instead of being filtered and perspective-correct.
  • EASEL re-reads the canvas only on an explicit texture.update() after needsUpdate is set, so the port does both every frame.
  • Pointer listeners are on the canvas with pointer capture instead of on the document, so drags start only on the example.
EASEL (Canvas2D)
This example needs a canvas-capable browser.

Loading scene…

three.js r186 (WebGL)
This example needs a canvas-capable browser.

Loading scene…

Loading scene…

Key API excerpt

import * as EASEL from "@xsyetopz/easel";


const geometry = new EASEL.SphereGeometry(5, 60, 40);
geometry.scale(-1, 1, 1);

const texture = new EASEL.CanvasTexture(panoramaCanvas);
texture.colorSpace = EASEL.SRGBColorSpace;
const material = new EASEL.BasicMaterial({ map: texture, vertexColors: false });

scene.add(new EASEL.Mesh(geometry, material));

drawPanoramaFrame(panoramaContext, time);
texture.needsUpdate = true;
texture.update();

const phi = EASEL.toRadians(90 - lat);
const theta = EASEL.toRadians(lon);
camera.position.set(
  0.5 * Math.sin(phi) * Math.cos(theta),
  0.5 * Math.cos(phi),
  0.5 * Math.sin(phi) * Math.sin(theta),
);
camera.lookAt(0, 0, 0);
renderer.prepare(scene, camera);
renderer.render(scene, camera);