Welcome..
Introduction to 3d, WebGL & WebVR.
WebGL - Web Graphics Library - is a JavaScript API for rendering 3D graphics in the browser, without plugins, allowing GPU accelerated usage of physics and image processing and effects. It is a Shader-based API using GLSL.
What is Three.js ?
A javascript 3d library, that abstracts away the complexities of coding 3d & the WebGL API - by Mr. Doob
How to get it :
- download just the minified build file.
Or :
-
download entire library, to explore the source and examples.(large file!)
-
install via npm & use a module bundler, such as rollup or webpack to build project files:
$ npm install three
- The
index.html
file - import three.js minified library
- import a WebVR utility script
- import our JS workshop code
<!DOCTYPE html>
<html lang="en">
<head>
<title>webvr workshop</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<style>
body {
background-color: #101010;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="./js/three.min.js"></script>
<script src="./js/WebVR.js"></script>
<script src="./js/workshop.js"></script>
</body>
- Open the
workshop.js
file in./js folder
- Create a Scene, a Camera, and a Renderer
var scene, camera, renderer;
init();
animate();
function init() {
setTheScene();
//createMesh();
//createLights();
//loadModel();
//createPanorama();
//enableVR();
}
function setTheScene(){
//set up scene
scene = new THREE.Scene();
//create camera
camera = new THREE.PerspectiveCamera( 90, window.innerWidth / window.innerHeight, 1, 1000 );
//create renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
renderer.animate( render );
}
function render() {
renderer.render( scene, camera );
}
- Open file in your WebGL capable browser
- Open the Dev Tools and inspect the Scene by typing scene in the console
Make a cube :
- Create a geometry
- Create a material
- Create a mesh object, and add the geometry and the material to the mesh
- Add the mesh to the scene
function createMesh(){
var geometry, material;
geometry = new THREE.BoxGeometry( 20, 20, 20 );
material = new THREE.MeshBasicMaterial({ color: 0x9988ff, wireframe: true});
mesh = new THREE.Mesh( geometry, material );
mesh.position.set( 0, 10, -50 );
scene.add( mesh );
}
- Declare the mesh at the top, so that it's accessable to us
var mesh;
- Add to render() to animate
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
- The Z dimension - 3D Cartesian Coordinates
- Remove the wireframe...
- Pick a material that reflects light.
material = new THREE.MeshStandardMaterial({ color: 0x9988ff });
- Add light to the scene
function createLights() {
var directionalLight = new THREE.DirectionalLight( 0xffeedd, 1 );
directionalLight.position.set( -100, 100, 50 );
scene.add( directionalLight );
}
- Change the geometry to Sphere and change colour of material and turn on flat shading in createMesh()
geometry = new THREE.SphereGeometry(10, 32, 16);
material = new THREE.MeshStandardMaterial({ color: 0xffffff, flatShading:true });
- Add extra lights in createLights()
var light = new THREE.SpotLight( 0xffffff, 0.5);
light.position.set( 50, -20, -20 );
scene.add( light );
var hemisphereLight = new THREE.HemisphereLight( 0x00aaff, 0xff43ff, 1 );
hemisphereLight.position.set( 0, 100, 0 );
scene.add( hemisphereLight );
- Remove rotation on X axis in render()
- explore the three.js editor
- load a 3D model
- attach a diffusion map texture
- export model with map as json
- Install node http-server ( if not already installed ):
npm install http-server -g
- Navigate to workshop folder, then run http server:
http-server . -p 8000
This step is optional, but you will get a warning in Chrome later on if accessing the WebVR API over an insecure connection.
- Navigate to workshop folder
- Create the cert-key pair files (valid for roughly 10 years)
openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
- ..then run https server:
http-server -p 8000 -S -C cert.pem
- Load the girl json file (./models/cirno.json)
- Position the model
- Add to Scene
function loadModel(){
// loading model
var loader = new THREE.ObjectLoader();
loader.load(
// resource URL
"models/cirno.json",
// pass the loaded data to the onLoad function.
function ( obj ) {
// add the loaded object to the scene
obj.position.set( 120, -100, -170 );
obj.scale.set( 0.1, 0.1, 0.1 );
scene.add( obj );
girl = obj;
},
// Function called when download progresses
function ( xhr ) {
console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
},
// Function called when download errors
function ( xhr ) {
console.error( 'An error happened' );
}
);
}
- Declare a referece to the girl model
var girl;
- so that we can animate her in render()
if(girl){
girl.rotation.y -= 0.01;
}
- Create a Sphere geometry (using BufferGeometry for performance )
- Invert the geometry on the x-axis so that all of the faces point inward, so that the image projects on the inside of a sphere
- Create basic material with a map
- Load a panoramic, equirectangular image as map texture
- Attach geometry & material to a mesh,
- Disable matrixAutoUpdate (performance) - our mesh will not move
- Add panorama mesh to scene
function createPanorama() {
var geometry = new THREE.SphereBufferGeometry( 500, 60, 40 );
geometry.scale( - 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( {
map: new THREE.TextureLoader().load( 'textures/south_bank_skate_park_small.jpg' )
} );
panorama = new THREE.Mesh( geometry, material );
panorama.matrixAutoUpdate = false;
scene.add( panorama );
}
Panoramic image by Jon Davey
WebVR is a JavaScript API for creating immersive 3D, Virtual Reality experiences in virtual reality devices or browsers.
Still an experimental feature in Chrome(59+), enable by switching on flag
chrome://flags#enable-webvr
or for live projects, request a Origin Token to enable by default on your domain.
- Enable VR in renderer
- Use the WebVR helper script to detect the device capabilities
function enableVR(){
//enable the renderer
renderer.vr.enabled = true;
// check if WebVR API is available
WEBVR.checkAvailability().catch( function( message ) {
document.body.appendChild( WEBVR.getMessageContainer( message ) );
} );
//check if there is a VR Display connected/enabled..
WEBVR.getVRDisplay( function ( display ) {
renderer.vr.setDevice( display );
document.body.appendChild( WEBVR.getButton( display, renderer.domElement ) );
} );
}
- Android Phone with the Google VR Services app installed ( requires Android OS version 6+ Marshmallow )
- Chrome browser
- VR Goggles (optional)
- Make sure you have your laptop and phone connected to the same network
- Use Chrome to navigate to your laptop's IP address + port number, i.e 192.168.0.2:8000
- Fingers crossed, you can now enjoy your master piece :)
- Controllers with no degrees of freedom (like Cardboard) These are controllers that are tied entirely to the viewport, and typically the interaction is assumed to originate in the center of the viewport.
- Controllers with 3 degrees of freedom (like the Daydream Controller). A controller with 3 degrees provides orientation information, but not location information. Typically such controllers are assumed to be held in the person’s left or right hand, and their position in 3D space is estimated.
- Controllers with 6 degrees of freedom (like the Oculus Rift or Vive). Any controller with 6 degrees of freedom will provide both orientation and location information. These are typically at the upper end of capabilities range, and have the best accuracy.
WebVR:
WebGL: