Autodesk Forge is now Autodesk Platform Services

13 Feb 2015

WebGL VR Effects with three.js

By Philippe Leefsma

This week post features some cool three.js effects that you can easily use to do VR. Two VR effects are now shipped out of the box with that great WebGL library:

- An Occulust Rift effect

- A Stereo Effect

They are pretty easy to apply to any standard three.js WebGL scene, all you need to do is passing your renderer to the effect and it will take care of splitting and distorting the view for you...

In order to properly test the effects, you need to download the attached sample and test it on your side, however if you use Chrome, you may hit some security restrictions as you open the page locally. This works fine in Firefox, which is more permissive regarding local html files. You would also need an Occulus headset if you want to see the VR effect, but that should give you an idea...

Here is how it looks like when running fullscreen - I had to disable the fullscreen feature for the demo embedded at the bootom of this post, as fullscreen mode didn't play well when run from that blog:

Screen Shot 2015-02-13 at 1.02.11 PM

Here is the demo and the controls for it:

- Rotating/Zooming the object using mouse

- "r" Key to switch to "Occulus Rift" effect

- "s" Key to switch to "Stereo" effect

- "n" Key to switch back to normal mode 

- For mobile: double tap to cycle through the view mode: normal > rift > stereo

Adsk.1500x1500
 


/////////////////////////////////////////////////////////////////////////
// Copyright (c) Autodesk, Inc. All rights reserved
// Written by Philippe Leefsma 2014 - ADN/Developer Technical Services
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
/////////////////////////////////////////////////////////////////////////
var Autodesk = {} || Autodesk;
Autodesk.ADN = {} || Autodesk.ADN;
/////////////////////////////////////////////////////////////////////////
// A Three.js demo that illustrates use of
// OculusRiftEffect & StereoEffect
/////////////////////////////////////////////////////////////////////////
Autodesk.ADN.EffectsDemo = function (canvasId) {
var _self = this;
var _canvasId = canvasId;
var _camera,
_scene,
_controls,
_mesh,
_renderer,
_glRenderer;
/////////////////////////////////////////////////////////////////////
// Resize handler
//
/////////////////////////////////////////////////////////////////////
_self.resizeCanvas = function () {
function getClientSize() {
var w = window,
d = document,
e = d.documentElement,
g = d.getElementsByTagName('body')[0],
sx = w.innerWidth || e.clientWidth || g.clientWidth,
sy = w.innerHeight || e.clientHeight || g.clientHeight;
return {x: sx, y: sy};
}
var size = getClientSize();
_camera.aspect = size.x / size.y;
_camera.updateProjectionMatrix();
_renderer.setSize(size.x, size.y);
var canvas = document.getElementById(_canvasId);
_controls = new THREE.TrackballControls(
_camera,
canvas);
_controls.rotateSpeed = 1.0;
_controls.minDistance = 200;
_controls.maxDistance = 6000;
_controls.addEventListener('change', render);
}
/////////////////////////////////////////////////////////////////////
// Initialize three.js scene
//
/////////////////////////////////////////////////////////////////////
function initializeScene() {
var canvas = document.getElementById(
_canvasId);
_camera = new THREE.PerspectiveCamera(
70, 1, 1, 10000);
_camera.position.z = 400;
_scene = new THREE.Scene();
var geometry = new THREE.BoxGeometry(
150, 150, 150);
var texture = THREE.ImageUtils.loadTexture(
'adsk.1500x1500.jpg');
var material = new THREE.MeshPhongMaterial( {
ambient: 0x030303,
color: 0xdddddd,
specular: 0x009900,
shininess: 30,
shading: THREE.FlatShading,
map: texture
});
var l1 = new THREE.DirectionalLight(0xffffff);
var l2 = new THREE.DirectionalLight(0xffffff);
var l3 = new THREE.DirectionalLight(0xffffff);
var l4 = new THREE.DirectionalLight(0xffffff);
l1.position.set(5, 0, 0).normalize();
l2.position.set(-5, 0, 0).normalize();
l3.position.set(0, 10, 0).normalize();
l4.position.set(10, 0, 10).normalize();
_scene.add(l1);
_scene.add(l2);
_scene.add(l3);
_scene.add(l4);
_mesh = new THREE.Mesh(geometry, material);
_scene.add(_mesh);
_renderer = _glRenderer = new THREE.WebGLRenderer({
canvas: canvas
});
_renderer.setPixelRatio(window.devicePixelRatio);
_renderer.setClearColor(0x1771C0, 1);
_self.resizeCanvas();
}
/////////////////////////////////////////////////////////////////////
// update callback
//
/////////////////////////////////////////////////////////////////////
function update() {
requestAnimationFrame(update);
_mesh.rotation.x += 0.01;
_mesh.rotation.y += 0.01;
_controls.update();
render();
}
/////////////////////////////////////////////////////////////////////
// render callback
//
/////////////////////////////////////////////////////////////////////
function render() {
_renderer.render(_scene, _camera);
}
/////////////////////////////////////////////////////////////////////
// set normal webgl renderer
//
/////////////////////////////////////////////////////////////////////
_self.setGlRenderer = function () {
initializeScene();
_self.resizeCanvas();
}
/////////////////////////////////////////////////////////////////////
// set occulus renderer
//
/////////////////////////////////////////////////////////////////////
_self.setOcculusRenderer = function () {
_renderer = new THREE.OculusRiftEffect(
_glRenderer,
{worldScale: 100});
_self.resizeCanvas();
}
/////////////////////////////////////////////////////////////////////
// set stereo renderer
//
/////////////////////////////////////////////////////////////////////
_self.setStereoRenderer = function () {
_renderer = new THREE.StereoEffect(_glRenderer);
_renderer.eyeSeparation = 0;
_self.resizeCanvas();
}
/////////////////////////////////////////////////////////////////////
// performs init
//
/////////////////////////////////////////////////////////////////////
initializeScene();
update();
}
/////////////////////////////////////////////////////////////////////////
// On document Ready
//
/////////////////////////////////////////////////////////////////////////
$( document ).ready(function() {
var demo = new Autodesk.ADN.EffectsDemo('renderer');
window.addEventListener('resize', function() {
demo.resizeCanvas();
} , false);
function setGlMode() {
THREEx.FullScreen.cancel();
demo.setGlRenderer();
}
function setOcculusMode() {
if (!THREEx.FullScreen.activated()) {
THREEx.FullScreen.request();
}
demo.setOcculusRenderer();
}
function setStereoMode() {
if (!THREEx.FullScreen.activated()) {
THREEx.FullScreen.request();
}
demo.setStereoRenderer();
}
var modeIdx = 0;
var modes = [
setGlMode,
setOcculusMode,
setStereoMode
];
$(document).keypress(function (event) {
switch (event.which) {
case 0: //ESC key
demo.setGlRenderer();
break;
case 102: //f key
if (THREEx.FullScreen.activated()) {
THREEx.FullScreen.cancel();
demo.setGlRenderer();
} else {
THREEx.FullScreen.request();
}
break;
case 110: //n key
setGlMode();
break;
case 114: //r key
setOcculusMode();
break;
case 115: //s key
setStereoMode();
break;
}
});
// Handle mobile touch events using Hammer lib
var mc = new Hammer.Manager(
document.getElementById("webGLDiv"));
mc.add(new Hammer.Tap({
event: 'doubletap',
taps: 2
}));
mc.add(new Hammer.Tap({
event: 'singletap'
}));
mc.get('doubletap').recognizeWith('singletap');
mc.get('singletap').requireFailure('doubletap');
mc.on("doubletap", function (ev) {
modeIdx = (++modeIdx) % 3;
modes[modeIdx]();
});
});
view raw vreffects.js hosted with ❤ by GitHub

Download Vr effects

Tags:

Related Article