canvas

panorama / equirectangular

What this shows

An equirectangular panorama mapped inside an inverted sphere; the view pans slowly, drag to look around and scroll to zoom.

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

Differences from three.js

  • Both sides show Greg Zaal's CC0 Poly Haven panorama spruit_sunrise_2k.hdr.jpg from the three.js repository instead of 2294472375_24a3b8ef46_o.jpg, whose license is unknown.
  • EASEL caches the 2048x1024 panorama at 128x128 and samples it nearest-neighbor with affine warping, so the full-screen view is very blocky and bends across each sphere face instead of being filtered and perspective-correct.
  • EASEL's TextureLoader.load returns nothing, so the port assigns the map in the load callback, where it also sets colorSpace and re-caches the already decoded texels with update(); the sphere draws untextured white until the data-URL JPEG is decoded.
  • Pointer move, pointer up and wheel listeners are attached to the canvas, with pointer capture, instead of the document, so dragging and zooming only start over 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(500, 60, 40);
geometry.scale(-1, 1, 1);

const material = new EASEL.BasicMaterial();
new EASEL.TextureLoader().load(panoramaUrl, (texture) => {
  texture.colorSpace = EASEL.SRGBColorSpace;
  texture.update().buildBrightnessLevels();
  material.map = texture;
});

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

lon += 0.1;
phi = EASEL.toRadians(90 - lat);
theta = EASEL.toRadians(lon);
camera.lookAt(
  500 * Math.sin(phi) * Math.cos(theta),
  500 * Math.cos(phi),
  500 * Math.sin(phi) * Math.sin(theta),
);
renderer.prepare(scene, camera);
renderer.render(scene, camera);