Skip to content

Commit

Permalink
fix: native webvr (#45)
Browse files Browse the repository at this point in the history
* feat: use orbit controls when no devices are found
* feat: update polyfill remove manager/boilerplate
* fix: move shaders to their own files
  • Loading branch information
brandonocasey authored Jan 22, 2018
1 parent a5cf671 commit 4b3a89f
Show file tree
Hide file tree
Showing 8 changed files with 260 additions and 327 deletions.
398 changes: 182 additions & 216 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"watch:js-modules": "rollup -c scripts/modules.rollup.config.js -w",
"watch:js-umd": "rollup -c scripts/umd.rollup.config.js -w",
"watch:test": "rollup -c scripts/test.rollup.config.js -w",
"prepublish": "npm run build",
"prepublish": "not-in-install && npm run build || in-install",
"prepush": "npm run lint",
"precommit": "npm run docs:toc && git add README.md"
},
Expand Down Expand Up @@ -92,8 +92,7 @@
"global": "^4.3.2",
"three": "^0.87.1",
"video.js": "^6.2.7",
"webvr-boilerplate": "^0.5.0",
"webvr-polyfill": "0.9.38"
"webvr-polyfill": "^0.10.2"
},
"devDependencies": {
"babel-plugin-external-helpers": "^6.22.0",
Expand All @@ -106,6 +105,7 @@
"doctoc": "^1.3.0",
"es5-shim": "^4.5.9",
"husky": "^0.13.3",
"in-publish": "^2.0.0",
"jsdoc": "^3.4.3",
"karma": "~1.3.0",
"karma-chrome-launcher": "^2.1.1",
Expand All @@ -115,7 +115,7 @@
"karma-qunit": "^1.2.1",
"karma-safari-launcher": "^1.0.0",
"mkdirp": "^0.5.1",
"node-sass": "4.5.3",
"node-sass": "^4.5.3",
"node-static": "^0.7.9",
"npm-run-all": "^4.0.2",
"qunitjs": "^1.21.0",
Expand Down
8 changes: 6 additions & 2 deletions scripts/rollup-replace.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@ export default function(options) {
'include': ['node_modules/three/examples/js/**'],
'delimiters': ['', ''],
'THREE.VRControls =': "var THREE = require('three');var VRControls;\nmodule.exports = VRControls =",
'THREE.VREffect =': "var THREE = require('three');var VREffect;\nmodule.exports = VREffect =",
'THREE.VRControls': 'VRControls',
'THREE.VREffect': 'VREffect'

'THREE.VREffect =': "var THREE = require('three');var VREffect;\nmodule.exports = VREffect =",
'THREE.VREffect': 'VREffect',

'THREE.OrbitControls =': "var THREE = require('three');var OrbitControls;\nmodule.exports = OrbitControls =",
'THREE.OrbitControls': 'OrbitControls'
}, options || {}));
}

137 changes: 53 additions & 84 deletions src/plugin.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import {version as VERSION} from '../package.json';
import window from 'global/window';
/* THIS CONFIGURES webvr-polyfill don't change the order */
import './webvr-config.js';
import 'webvr-polyfill/src/main';
import WebVRPolyfill from 'webvr-polyfill';
import videojs from 'video.js';
import * as THREE from 'three';
import VRControls from 'three/examples/js/controls/VRControls.js';
import VREffect from 'three/examples/js/effects/VREffect.js';
import WebVRManager from 'webvr-boilerplate/build/webvr-manager';
import OrbitControls from 'three/examples/js/controls/OrbitControls.js';
import rgbFragmentShader from './rgb-fragment-shader';
import rgbaFragmentShader from './rgba-fragment-shader';
import vertexShader from './vertex-shader';

// import controls so they get regisetered with videojs
import './cardboard-button';
import './big-vr-play-button';

window.WebVRManager = WebVRManager;

const validProjections = [
'360',
'360_LR',
Expand All @@ -35,11 +34,6 @@ const defaults = {
};

const errors = {
'web-vr-no-devices-found': {
headline: 'No 360 devices found',
type: '360_NO_DEVICES_FOUND',
message: 'Your browser supports 360, but no 360 displays found.'
},
'web-vr-out-of-date': {
headline: '360 is out of date',
type: '360_OUT_OF_DATE',
Expand Down Expand Up @@ -106,6 +100,10 @@ class VR extends Plugin {

super(player, settings);

this.polyfill_ = new WebVRPolyfill({
TOUCH_PANNER_DISABLED: false
});

this.options_ = settings;
this.player_ = player;
this.bigPlayButtonIndex_ = player.children().indexOf(player.getChild('BigPlayButton')) || 0;
Expand Down Expand Up @@ -269,17 +267,27 @@ class VR extends Plugin {
}

handleVrDisplayActivate_() {
this.manager.enterVRMode_();
this.manager.setMode_(3);
if (!this.vrDisplay) {
return;
}
this.vrDisplay.requestPresent([{source: this.renderedCanvas}]);
}

handleVrDisplayDeactivate_() {
if (!this.vrDisplay.isPresenting) {
if (!this.vrDisplay || !this.vrDisplay.isPresenting) {
return;
}
this.vrDisplay.exitPresent();
}

requestAnimationFrame(fn) {
if (this.vrDisplay) {
return this.vrDisplay.requestAnimationFrame(fn);
}

return super.requestAnimationFrame(fn);
}

togglePlay_() {
if (this.player_.paused()) {
this.player_.play();
Expand All @@ -296,31 +304,22 @@ class VR extends Plugin {
}

this.controls3d.update();
this.manager.render(this.scene, this.camera);
this.effect.render(this.scene, this.camera);

if (!this.vrDisplay) {
this.animationFrameId_ = this.requestAnimationFrame(this.animate_);
this.camera.getWorldDirection(this.cameraVector);
return;
}

this.animationFrameId_ = this.vrDisplay.requestAnimationFrame(this.animate_);
this.animationFrameId_ = this.requestAnimationFrame(this.animate_);

if (!window.navigator.getGamepads) {
return;
}
// Grab all gamepads
const gamepads = window.navigator.getGamepads();
if (window.navigator.getGamepads) {
// Grab all gamepads
const gamepads = window.navigator.getGamepads();

for (let i = 0; i < gamepads.length; ++i) {
const gamepad = gamepads[i];
for (let i = 0; i < gamepads.length; ++i) {
const gamepad = gamepads[i];

// Make sure gamepad is defined
if (!gamepad) {
continue;
}
// Only take input if state has changed since we checked last
if (gamepad.timestamp && !(gamepad.timestamp === this.prevTimestamps_[i])) {
// Make sure gamepad is defined
// Only take input if state has changed since we checked last
if (!gamepad || !gamepad.timestamp || gamepad.timestamp === this.prevTimestamps_[i]) {
continue;
}
for (let j = 0; j < gamepad.buttons.length; ++j) {
if (gamepad.buttons[j].pressed) {
this.togglePlay_();
Expand Down Expand Up @@ -366,7 +365,6 @@ class VR extends Plugin {
}

this.scene = new THREE.Scene();
this.controls3d = new VRControls(this.camera);

this.videoTexture = new THREE.VideoTexture(this.getVideoEl_());

Expand All @@ -392,45 +390,17 @@ class VR extends Plugin {
this.videoTexture.format = THREE.RGBFormat;
}

if (this.videoTexture.format === THREE.RGBAFormat && this.videoTexture.flipY === false) {
this.movieMaterial = new THREE.ShaderMaterial({
uniforms: {
texture: { value: this.videoTexture }
},
vertexShader: [
'varying vec2 vUV;',
'void main() {',
' vUV = vec2( uv.x, 1.0 - uv.y );',
' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
'}'
].join('\n'),
fragmentShader: [
'uniform sampler2D texture;',
'varying vec2 vUV;',
'void main() {',
' gl_FragColor = texture2D( texture, vUV ).bgra;',
'}'
].join('\n')
});
} else if (this.videoTexture.format === THREE.RGBFormat && this.videoTexture.flipY === false) {
if ((this.videoTexture.format === THREE.RGBAFormat || this.videoTexture.format === THREE.RGBFormat) && this.videoTexture.flipY === false) {
let fragmentShader = rgbFragmentShader;

if (this.videoTexture.format === THREE.RGBAFormat) {
fragmentShader = rgbaFragmentShader;
}

this.movieMaterial = new THREE.ShaderMaterial({
uniforms: {
texture: { value: this.videoTexture }
},
vertexShader: [
'varying vec2 vUV;',
'void main() {',
' vUV = vec2( uv.x, 1.0 - uv.y );',
' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
'}'
].join('\n'),
fragmentShader: [
'uniform sampler2D texture;',
'varying vec2 vUV;',
'void main() {',
' gl_FragColor = texture2D( texture, vUV );',
'}'
].join('\n')
uniforms: {texture: {value: this.videoTexture}},
vertexShader,
fragmentShader
});
} else {
this.movieMaterial = new THREE.MeshBasicMaterial({ map: this.videoTexture, overdraw: true, side: THREE.DoubleSide });
Expand Down Expand Up @@ -477,8 +447,6 @@ class VR extends Plugin {
// Previous timestamps for gamepad updates
this.prevTimestamps_ = [];

this.manager = new WebVRManager(this.renderer, this.effect, {hideButton: true});

this.renderedCanvas = this.renderer.domElement;

const debounce = function(fn, wait) {
Expand Down Expand Up @@ -514,24 +482,26 @@ class VR extends Plugin {
this.getVideoEl_().style.display = 'none';

if (window.navigator.getVRDisplays) {
this.log('VR is supported, getting vr displays');
window.navigator.getVRDisplays().then((displays) => {
if (displays.length > 0) {
this.log('WebVR supported, VRDisplays found.');
this.log('VR Displays found', displays);
this.vrDisplay = displays[0];
this.log(this.vrDisplay);
this.log('Going to use VRControls on the first one', this.vrDisplay);

// Native WebVR Head Mounted Displays (HMDs) like the HTC Vive
// also need the cardboard button to enter fully immersive mode
// so, we want to add the button if we're not polyfilled.
if (!this.vrDisplay.isPolyfilled) {
this.addCardboardButton_();
}
// FIREFOX doesn't report the polyfill display as a
// VRDisplay so this would error even though the video would
// work
} else if (!videojs.browser.IS_FIREFOX) {
this.triggerError_({code: 'web-vr-no-devices-found', dismiss: false});
this.controls3d = new VRControls(this.camera);
} else {
this.log('no vr displays found going to use OrbitControls');
this.controls3d = new OrbitControls(this.camera, this.renderedCanvas);
this.controls3d.target.set(0, 0, -1);
}
this.requestAnimationFrame(this.animate_);
});
} else if (window.navigator.getVRDevices) {
this.triggerError_({code: 'web-vr-out-of-date', dismiss: false});
Expand All @@ -545,7 +515,6 @@ class VR extends Plugin {
window.addEventListener('vrdisplayactivate', this.handleVrDisplayActivate_, true);
window.addEventListener('vrdisplaydeactivate', this.handleVrDisplayDeactivate_, true);

this.animate_();
this.initialized_ = true;
}

Expand Down
5 changes: 5 additions & 0 deletions src/rgb-fragment-shader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = `uniform sampler2D texture;
varying vec2 vUV;
void main() {
gl_FragColor = texture2D(texture, vUV);
}`;
5 changes: 5 additions & 0 deletions src/rgba-fragment-shader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = `uniform sampler2D texture;
varying vec2 vUV;
void main() {
gl_FragColor = texture2D(texture, vUV).bgra;
}`;
5 changes: 5 additions & 0 deletions src/vertex-shader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = `varying vec2 vUV;
void main() {
vUV = vec2( uv.x, 1.0 - uv.y );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`;
21 changes: 0 additions & 21 deletions src/webvr-config.js

This file was deleted.

0 comments on commit 4b3a89f

Please sign in to comment.