With Oculus, Samsung Gear, Google Cardboard, and more headsets rushing to market, it's an exciting time to enter the world of virtual reality. With frameworks from Mozilla WebVR, Unity, LeapMotion and others providing support, Javascript developers can literally get into the game.
In this talk, we'll walkthrough a simple WebVR program to see:
* the ease of getting started
* the technical, design, and UX challenges faced
* the roadmap of things to come
32. Download ALL THE THINGS!
Drivers and SDK from developer.oculus.com
Firefox WebVR Browser from mozvr.com/downloads
Chromium WebVR Browser from bit.ly/1DPjgDQ
46. no_vr.js - Create a Renderer
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75, window.innerWidth / window.innerHeight, 0.3, 10000
);
var light = new THREE.PointLight(0xffffff, 1.0, 0);
light.position.set(0,0,0);
scene.add(light);
var bitGeometry = new THREE.DodecahedronGeometry(0.5);
47. no_vr.js - Let Your Scene be Seen
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75, window.innerWidth / window.innerHeight, 0.3, 10000
);
var light = new THREE.PointLight(0xffffff, 1.0, 0);
light.position.set(0,0,0);
scene.add(light);
var bitGeometry = new THREE.DodecahedronGeometry(0.5);
48. no_vr.js - Let there be light!
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75, window.innerWidth / window.innerHeight, 0.3, 10000
);
var light = new THREE.PointLight(0xffffff, 1.0, 0);
light.position.set(0,0,0);
scene.add(light);
var bitGeometry = new THREE.DodecahedronGeometry(0.5);
49. no_vr.js - Have Something to See
var light = new THREE.PointLight(0xffffff, 1.0, 0);
light.position.set(0,0,0);
scene.add(light);
var bitGeometry = new THREE.DodecahedronGeometry(0.5);
var bitMaterial = new THREE.MeshLambertMaterial({
color: 0x00ffff, shading: THREE.FlatShading
});
var bit = new THREE.Mesh(bitGeometry, bitMaterial);
bit.position.z = -2;
scene.add(bit);
var planeGeometry =
new THREE.PlaneBufferGeometry(1000, 1000, 1000);
var planeMaterial = new THREE.MeshPhongMaterial({
64. Nearly all WebVR demos use
VRControls and VREffect
Found in three.js examples alongside other great
utilities.
github.com/mrdoob/three.js/tree/master/examples/js
67. basic_vr.js - Introduce VRControls
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75, window.innerWidth / window.innerHeight, 0.3, 10000
);
var controls = new THREE.VRControls(camera);
var effect = new THREE.VREffect(renderer);
effect.setSize(window.innerWidth, window.innerHeight);
var light = new THREE.PointLight(0xffffff, 1.0, 15);
light.position.set(0,0,0);
69. VRControl.js - Initialization
function gotVRDevices( devices )
devices = filterInvalidDevices( devices );
for ( var i = 0; i < devices.length; i ++ ) {
if ( devices[ i ] instanceof PositionSensorVRDevice ) {
vrInputs.push( devices[ i ] );
}
}
if ( onError ) onError( 'HMD not available' );
}
if ( navigator.getVRDevices ) {
navigator.getVRDevices().then( gotVRDevices );
}
70. basic_vr.js - Introduce VREffect
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75, window.innerWidth / window.innerHeight, 0.3, 10000
);
var controls = new THREE.VRControls(camera);
var effect = new THREE.VREffect(renderer);
effect.setSize(window.innerWidth, window.innerHeight);
var light = new THREE.PointLight(0xffffff, 1.0, 15);
light.position.set(0,0,0);
72. VREffect.js - Initialization
function gotVRDevices( devices ) {
for ( var i = 0; i < devices.length; i ++ ) {
if ( devices[ i ] instanceof HMDVRDevice ) {
///…
}
if ( vrHMD === undefined ) {
if ( onError ) onError( 'HMD not available' );
}
}
73. VREffect.js - Remember the "..."
var eyeParamsL = vrHMD.getEyeParameters( 'left' );
var eyeParamsR = vrHMD.getEyeParameters( 'right' );
eyeTranslationL = eyeParamsL.eyeTranslation;
eyeTranslationR = eyeParamsR.eyeTranslation;
eyeFOVL = eyeParamsL.recommendedFieldOfView;
eyeFOVR = eyeParamsR.recommendedFieldOfView;
74. basic_vr.js - Go Full Screen
var vrMode = false;
function enterVR() {
effect.setFullScreen(true);
vrMode = true;
}
function exitVR() {
effect.setFullScreen(false);
vrMode = false;
};
function toggleVR() {
if (!vrMode) {
enterVR();
75. VREffect - Full Screen VR display
this.setFullScreen = function ( boolean ) {
if ( vrHMD === undefined ) return;
if ( isFullscreen === boolean ) return;
if ( canvas.mozRequestFullScreen ) {
canvas.mozRequestFullScreen( { vrDisplay: vrHMD } );
} else if ( canvas.webkitRequestFullscreen ) {
canvas.webkitRequestFullscreen( { vrDisplay: vrHMD } );
}
};
76. basic_vr.js - Let Reality Take Control
function animate(time) {
bit.position.x = Math.sin(time/1000) * 2;
bit.position.y = Math.sin(time/2000);
bit.rotation.y += 0.01;
bit.rotation.z += 0.01;
controls.update();
effect.render(scene, camera);
requestAnimationFrame( animate );
}
animate();
77. VRControls.js - Get State from VR Device
this.update = function () {
for ( var i = 0; i < vrInputs.length; i ++ ) {
var vrInput = vrInputs[ i ];
var state = vrInput.getState();
if ( state.orientation !== null ) {
object.quaternion.copy( state.orientation );
}
if ( state.position !== null ) {
object.position.copy( state.position )
.multiplyScalar( scope.scale );
}
}
};
79. Two Cameras for the price of
ONE!
It creates a camera for each eye, shifts them from the
main camera location based on HMDVRDevice eye
information, then renders the view for each!
90. Simulator Sickness is Real …
Need to hit 60-90 fps.
Motion data already laggy.
Additional disadvantage of being in browser.
More graphics you push the harder this gets.
107. raycast.js - Gaze
var raycaster = new THREE.Raycaster();
var center = new THREE.Vector2();
function gaze() {
if(!audioPlaying) {
raycaster.setFromCamera(center, camera);
var intersects = raycaster.intersectObjects([bit]);
if (intersects.length > 0) {
audioPlaying = true;
if (Math.random() < 0.5) {
switchBitTo(1);
yes.play();
} else {
switchBitTo(0);
no.play();
111. Unity publishes to multiple
platforms
Plugins for VR available. Support directly baked in 5.1
112.
113.
114. #pragma strict
var center : GameObject;
var axis : Vector3;
function Start () {
}
function Update () {
transform.RotateAround(
center.transform.position, axis,30 * Time.deltaTime
);
}
Orbit.js
115. Cores.js
function beingLookedAt() {
var hit : RaycastHit;
var ray = new Ray(Camera.main.transform.position,
Camera.main.transform.forward);
return GetComponent
.<Collider>()
.Raycast(ray, hit, Mathf.Infinity);
}