Three Dimensions Good – Crafting a 3D Web with Three.js



Three Dimensions Good – Crafting a 3D Web with Three.js

0 1


async-threejs

Async THREE.js talk

On Github Kyrand / async-threejs

Three Dimensions Good

Crafting a 3D Web with Three.js

Heads Up

Three.js is a library that aims to take the pain out of creating 3D worlds in WebGL. How it does this and how well is the main thrust of this talk...

- Kyran Dale / @hakimel

Oh hey, these are some notes. They'll be hidden in your presentation, but you can see them if you run the speaker notes server.

The Shape of Things to Come

  • The good, the bad and the ugly.
  • Basic scene-setting.
  • A little geometry lesson.
  • A procedural fireworks display.

The Good, the Bad, and the Ugly of THREE.js

The Good

The Bad

You can't avoid a little maths. You don't have to love vectors and matrices but you should try and feel a little fondness for them.

The Ugly

  • Documentation is for wimps.
  • API and core changing all the time.

What to do about it

  • http://threejsdoc.appspot.com/
  • Print out key components, at least Vector3 and Matrix3 classes.
  • There's a deal of clean, well-commented demos out there.
  • Watch those version numbers!!!
  • Stackoverflow is your friend.

Basic Setup

var SCENE_WIDTH = 800, SCENE_HEIGHT = 600,
// camera attributes
CAMERA_VIEW_ANGLE = 45,
CAMERA_ASPECT = SCENE_WIDTH / SCENE_HEIGHT,
// we'll be attaching the scene to a DOM element
scene_container = $('#container'),
// THREE.js key elements
// This will do the actual GL-drawing:
renderer = new THREE.WebGLRenderer(),
// This is the eye on the world:
camera = new THREE.PerspectiveCamera(
    CAMERA_VIEW_ANGLE, CAMERA_ASPECT, 0.1/*NEAR*/, 1000/*FAR*/
),
// This sets the... 
scene = new THREE.Scene();
// Now to hook up the THREE.js pieces
scene.add(camera)
// pull camera back to better vantage point
camera.position.z = 300;
// set renderer's size
renderer.setSize(SCENE_WIDTH, SCENE_HEIGHT);
// and attach to our container DOM 
scene_container.append(renderer.domElement);
                                            
					

Basic Setup

Creating a world

// Adding a cube...
var cube = new THREE.Mesh(
    new THREE.CubeGeometry(50,50,50),
    new THREE.MeshBasicMaterial( {color: 0x111111, opacity:1})
);
scene.add(cube);
renderer.render(scene, camera);
                                            
					

Creating a world

Let there be lights

// some light on the situation
var cube = new THREE.Mesh(
    new THREE.CubeGeometry(50,50,50),
//    new THREE.MeshBasicMaterial( {color: 0x111111, opacity:1})
    new THREE.MeshLambertMaterial( {color: 0xcccccc})

);
scene.add(cube);
// some light on the situation
var light = new THREE.SpotLight();
light.position.set( 150, 150, 150 );
scene.add(light);

camera.position.y = 50;
cube.rotation.y += 0.7; // !NOTE! all rotations in radians

renderer.render(scene, camera);
                                            
					

Let there be lights

Wrapping the box...


// A grey background for the white texture
renderer.setClearColorHex(0xEEEEEE, 1.0); 
// Add a texture-map to the cube
var cube = new THREE.Mesh(
    new THREE.CubeGeometry(50,50,50),
    // new THREE.MeshBasicMaterial( {color: 0x111111, opacity:1})
    // new THREE.MeshLambertMaterial( {color: 0xcccccc})
    new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( '/images/async_logo.jpg' ) })
);
scene.add(cube);
// and animate
animate();
function animate() {
    requestAnimationFrame( animate );
    renderer.render(scene, camera);
}
					

Wrapping the box...

Putting a spin on things


var last_t = new Date().getTime();
function animate(t) {
     // smoothly rotate about y (our up) axis  
     cube.rotation.y += (t-last_t)*0.001;
     last_t = t;
     requestAnimationFrame(animate);
     renderer.render(scene, camera);
};
animate(new Date().getTime());
					

Putting a spin on things

A little construction work

function add_cube(x, y, z){
    var cube = new THREE.Mesh(
        new THREE.CubeGeometry(50,50,50),
        new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( '/images/async_logo.jpg' ) })
    );
    cube.position.set(x, y, z);
    scene.add(cube);
    return cube;
}

var scene_cubes = [];
scene_cubes.push(add_cube(0, 0, 0));
scene_cubes.push(add_cube(0, 50, 0));
scene_cubes.push(add_cube(0, 100, 0));

function animate(t) {
     for(i in scene_cubes){
         cube = scene_cubes[i];
         cube.rotation.y += 2 * (i%2 - 0.5) * (t-last_t)*0.001;
     }
     last_t = t;
     requestAnimationFrame(animate);
     renderer.render(scene, camera);
};
					

A little construction work

Adding a skybox

    cameraCube = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 100000 );
    sceneCube = new THREE.Scene();
    var path = "/images/cube/skybox/";
    var format = '.jpg';
    var urls = [
	path + 'px' + format, path + 'nx' + format,
	path + 'py' + format, path + 'ny' + format,
	path + 'pz' + format, path + 'nz' + format
    ];

    var textureCube = THREE.ImageUtils.loadTextureCube( urls, new THREE.CubeRefractionMapping() );
    var material = new THREE.MeshBasicMaterial( { color: 0xffffff, envMap: textureCube, refractionRatio: 0.95 } );

    // [ a little shader boiler-plate ]

    mesh = new THREE.Mesh( new THREE.CubeGeometry( 100, 100, 100 ), material );
    sceneCube.add( mesh );
    // in animate cycle
    renderer.render( sceneCube, cameraCube );
                                            
					

Adding a sky-box

Global and local coordinates

Making a little fireworks display

Acknowledgements

  • Mr Doob and friends
  • Paul Lewis at Aerotwist
  • Ilmari Heikkinen - Google labs
  • Evgeny Demidov - Ibiblio

THE END

BY Kyran Dale