Sphere Video

by dustinkerstein

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

CSS

body,
canvas {
    margin: 0;
    padding: 0;
}

body {
    overflow: hidden;
}

JavaScript

// MAKE SURE TO CLICK INTO THE RESULT IFRAME OR ELSE SAFARI WILL ONLY RENDER RAF / SETINTERVAL AT MAX 30FPS DUE TO POWER SAVING CODE

var mesh, geometry, camera, material, scene, renderer, texture, controls;
var index = 0;
var url = "https://data.panomoments.com/processed/5a5fcbcbb9a588000ffbd7a2/5a5fcc53b9a588000ffbd7a3/hd_dashinit.mp4"; // 100% I-Frames for fast seeking
var video = document.createElement('video');
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 1;
scene = new THREE.Scene();
video.preload = "auto";
video.muted = true;
video.autoplay = true; // Needed for iOS to trigger readyState = 4
video.loop = true;
texture = new THREE.Texture(video);
texture.minFilter = THREE.LinearFilter;
texture.format = THREE.RGBFormat;
scene.add(camera);
material = new THREE.MeshBasicMaterial({ map: texture });
geometry = new THREE.SphereBufferGeometry(400, 60, 40, (Math.PI / 2 - THREE.Math.degToRad(360) / 2), THREE.Math.degToRad(360), (Math.PI / 2 - THREE.Math.degToRad(180) / 2), THREE.Math.degToRad(180));
geometry.scale(-1, 1, 1);
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
//camera.add(mesh);
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;

renderer.setAnimationLoop(render)

function render() {
  if (video.readyState >= 3) { 
    texture.needsUpdate = true;
    index = (index + 1) % 299;
    video.currentTime = index;
  }
  controls.update();
  renderer.render(scene, camera);
}

fetch(url).then(function(response) {
  response.blob().then(function(myBlob) {
    video.src = window.URL.createObjectURL(myBlob); // Seeking with blob occasionally shows XPC memory issue on Safari but even with this issue you should be able ot see that rAF performs worse than...