Planet WebGL

May 17, 2012

Learning WebGL

WebGL around the net, 17 May 2012

by giles at May 17, 2012 03:07 PM

May 15, 2012

Learning Three.js

Punch A Doom Character in Augmented Reality

Did you ever dreamed of punching a doom character ? They look evil and killed you so many time while you were playing the game. It is revenge time! This post will help you realize your dream :) It is about a minigame called "Punch A Doom Character in Augmented Reality" because in this game, the player can punch Doom Character in augmented reality :)

The character is displayed in 3D with WebGL with three.js. The player gestures are recognized thru the webcam by augmentedgesture.js library. It uses WebRTC getUserMedia to get the webcam using open standards. You can play this minigame here. In fact, it is an example of augmentedgesture.js library. We will walk you thru the code. Only 60 lines of Javascript.

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="349" src="http://www.youtube.com/embed/Aa9945MGRL0" width="425"></iframe>

We have seen augmented gesture in "Augmented Reality 3D Pong" post and MD2 Characters in "tQuery Plugin for Doom Characters" post. Now we gonna associate them together in our mini game :) I presented it at Web-5 conference in april. At the time, i recorded a preview "Doom: a new workout for geek?". Now let's get started!

The 3D World

First we initialize the world in 3D. With tQuery.createWorld(), we create a tQuery.World. With .boilerplate(), we setup a boilerplate on this world. A boilerplate is a fast way to get you started on the right foot. It is the learningthreejs boilerplate for three.js. With .start(), we start the rendering loop. So from now on, the world scene gonna be rendered periodically, typically 60time per seconds.

```

var world   = tQuery.createWorld().boilerplate().start();

```

We setup the camera now. We remove the default camera controls from the boilerplate. Then we put the camera at (0,1.5,5) and looking toward (0,1,-1)

```

world.removeCameraControls()
world.camera().position.set(0,1.5, 4);
world.camera().lookAt(new THREE.Vector3(0,1,-1));

```

Now we change the background color. This confusing line ensure the background of the 3D scene will be rendered as 0x000000 color, aka black. We set a black background to give an impression of night.

```

world.renderer().setClearColorHex( 0x000000, world.renderer().getClearAlpha() );

```

We had a fog to the scene. For that, we use tquery.world.createfog.js plugins.

```

world.addFogExp2({density : 0.15});

```

The Lights

Here we setup the lights of our scene. This is important as it determine how your scene looks. We add a ambient light and a directional light.

```

tQuery.createAmbientLight().addTo(world).color(0x444444);
tQuery.createDirectionalLight().addTo(world).position(-1,1,1).color(0xFFFFFF).intensity(3);

```

The Ground

We create a large checkerboard with tquery.checkerboard.js plugin. We scale the checkerboard to 100 per 100 units in the 3D world. Thus it is quite large and disappears into the fog. It gives the cheap impression of an infinite checkerboard.

```

tQuery.createCheckerboard({
    segmentsW   : 100,  // number of segment in width
    segmentsH   : 100   // number of segment in Height
}).addTo(world).scaleBy(100);

```

The Character

We use tQuery.RatamahattaMD2Character plugin. Its inherits from tQuery.MD2Character plugin. All the configuration for this particular character ratamahatta is already done for you. We attach it to tQuery world.

```

var character   = new tQuery.RatamahattaMD2Character().attach(world);

```

When an animation is completed, switch to animation 'stand'.

```

character.bind('animationCompleted', function(character, animationName){
    console.log("anim completed", animationName);
    this.animation('stand');
});

```

Recognize Augmented Gestures

First we instanciate an object of AugmentedGesture class. .enableDatGui() will add a Dat.GUI. This is a nice library to tune parameters. We use it to tune augmentedgesture pointers. You can read more about it in "Dat-gui - Simple UI for Demos" post. .start() asks it to begin monitoring the webcam and see if it finds markers. .domElementThumbnail() put the webcam view as a thumbnail on the screen. This is what you see on top-left. This is usefull for the user, it is used as feedback to know what is happening

```

var aGesture    = new AugmentedGesture().enableDatGui().start().domElementThumbnail();

```

The Pointers

Now that we got our AugmentedGesture instance, we gonna configure the pointers. One for the right hand, one for the left hand. For each, we setup the options to adapt each hand colors. In my case, the right hand is containing a green ball and the left hand contains a red ball.

```

var pointerOpts = new AugmentedGesture.OptionPointer();
pointerOpts.pointer.crossColor  = {r:    0, g: 255, b:   0};
pointerOpts.colorFilter.r   = {min:   0, max:  95};
pointerOpts.colorFilter.g   = {min: 115, max: 255};
pointerOpts.colorFilter.b   = {min:  25, max: 150};
aGesture.addPointer("right", pointerOpts);

```

Now we do the same for the left pointer.

```

var pointerOpts = new AugmentedGesture.OptionPointer();
pointerOpts.pointer.crossColor  = {r:    255, g:   0, b: 128};
pointerOpts.colorFilter.r   = {min: 190, max: 255};
pointerOpts.colorFilter.g   = {min:  30, max: 255};
pointerOpts.colorFilter.b   = {min:   0, max: 100};
aGesture.addPointer("left", pointerOpts);

```

Gesture Analysis

Now that augmentedgesture.js is giving us the position of each hand, we gonna convert that into events. punchingRight when the user gives a punch with the right hand and punchingLeft for the left hand. We establish a variable to store the user moves. It is quite simple .punchingRight is true when the use is punching with his right hand. .punchingLeft is the same for the left hand. and .changed is true when values change.

```

var userMove    = {
    punchingRight   : false,
    punchingLeft    : false,
    changed     : false
};

```

we bind the event mousemove.left thus we are notified when the user moves his left hand. The algo we use is very simple: if the left hand is on the right part of the screen, then the user is considered "punchingLeft". Dont forget to .changed to true

```

aGesture.bind("mousemove.left", function(event){
    var state   = event.x > 1 - 1/3;
    if( state === userMove.punchingLeft )   return;
    userMove.punchingLeft   = state;
    userMove.changed    = true;
});

```

Now we need the same thing for the other hand. all the the same.

```

aGesture.bind("mousemove.right", function(event){
    var state   = event.x < 1/3;
    if( state === userMove.punchingRight )  return;
    userMove.punchingRight  = state;
    userMove.changed    = true;
});

```

Bind Character and Augmented Gestures

Now we hook a function to the rendering loop. This function will be executed every time the scene is renderered. The first thing we do in this function is to check that userMove has .changed. If not, we do nothing.

```

world.loop().hook(function(){
    if( userMove.changed === false )    return;
    userMove.changed = false;

```

Now we process each move of the user. If the user is punchingRight, play the animation crdeath of the character. If he is punchingLeft, play crplain.

```

    if( userMove.punchingRight )        character.animation('crdeath');
    else if( userMove.punchingLeft )    character.animation('crpain');
});

```

And you are DONE! Pretty nice no ? :)

Conclusion

In this post we built a mini-game where users can punch doom character in augmented reality. All that in 60 lines of javascript. The Character is displayed in WebGL with three.js and the augmented reality is handled by augmentedgesture.js. I like how those libraries makes the code so small, and the developement time so short.

That's all folks, have fun :)

May 15, 2012 09:59 AM

May 10, 2012

Learning WebGL

WebGL around the net, 10 May 2012

A somewhat shorter list this week:

Got a WebGL demo you want me to put in next week’s roundup? Leave a comment below, or drop me a line!

by giles at May 10, 2012 12:35 PM

May 08, 2012

Learning WebGL

Announcing WebGL Jobs

Quite a few people have contacted me about hiring WebGL developers — and I’m sure quite a few people reading this blog are interested in working on WebGL stuff professionally. So I’ve put together a little jobs board, WebGL Jobs (snappy name, huh?), where people who want to hire people can post what they want to hire them for.

There’s an RSS feed and an associated Twitter account; only one job listed so far, a freelance position at at Ergoe, a London-based company (though I think they’re looking for people globally). Why not head on over and take a look?

WebGL Jobs is kindly hosted by PythonAnywhere (my day job), and the code is available on GitHub if you’re interested in looking at an unbelievably basic Django app :-)

by giles at May 08, 2012 01:15 PM

Learning Three.js

Sound Visualisation: a Vuemeter in WebGL

This post is about producing a 3D Vuemeter for real time sound. We gonna walk thru the code of a webaudio.js example. This example will show you how to create a WebGL vuemetter with webaudio.js. It should be simple to understand, only 40-lines of javascript. webaudio.js is a web audio library for game. We gonna use it to reach Web Audio API. We gonna use tQuery to reach three.js 3D engine.

webaudio.js has been first coded as a tQuery plugin. You can find a post about it on learningthreejs blog. But this technology is so nice, it deserved its own repository. The library gained in flexibility in the process: It is now possible to display histogram in canvas2D of simply play sound, with no 3D at all :) see here for a list of webaudio.js examples.

Try the demo. This is the result that we gonna build together. Below is a small screencast of me presenting the code.

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="349" src="http://www.youtube.com/embed/--Gv2EI2a-U" width="425"></iframe>

Background Knowledge

Web Audio API is aimed for games and based on openAL. Its API is real nice tho. It is Efficient and flexible. It is efficient because most processing happen in native code, still you configure it in js, your favorite language :) It is flexible as it is based on a routing concept which give you great controls on the sounds you play.

You can find many good tutorials on the matter on html5rocks. I recently did a presentation at musichackparis on Web Audio API. If you want to know more, slides are here. This API is available on WebKit based browser, so safari and chrome and its derivative. Unfortunatly this API isn't compatible with major webgl browsers e.g. firefox and opera. The Web Audio API is real nice tho. Efficient flexible Sound is still the poor lone child of the web :( Well let's have fun with what we have.

Let's get started

Ok the very begining is real simple. We init a basic html page. Then we include the dependancies in javascript. We include webaudio.js to handle the sound playing and analysis. Then we just have to include tquery. tquery-bundle.js is tquery bundled with three.js in a single file for convenience.

```

<!doctype html><title>webaudio example: histo3d</title>
<script src="../build/webaudio.js"></script>
<script src="vendor/tquery/tquery-bundle.js"></script>
<body><script>

```

Let's Code in JS

First we gonna intenciate WebAudio. This will initialize the layer. It will create the AudioNode`s for the end of the chain. By default it contains a gainNode and a compressorNode. The gainNode is used to tune the volume. and the compressNode to smooth the peaks we could hit in the sound.

```

var webaudio    = new WebAudio();

```

Now that we go webaudio available, let's use it to create the sound we gonna play. .createSound() will create a WebAudio.Sound. Then we .load() it from this url 'sounds/perfume.mp3'. The callback will be notified as soon as the sound is loaded. Then we simply start to play it. Don't forget to get .loop(true) thus the sound will loop forever.

```

var sound   = webaudio.createSound().load('sounds/perfume.mp3', function(sound){
    sound.loop(true).play();
});

```

Initialize the 3D World

First we initialize the world in 3D. With tQuery.createWorld(), we create a tQuery.World. With .boilerplate(), we setup a boilerplate on this world. A boilerplate is a fast way to get you started on the right foot. It is the learningthreejs boilerplate for three.js With .start(), we start the rendering loop. So from now on, the world scene gonna be rendered periodically, typically 60time per seconds.

```

var world   = tQuery.createWorld().boilerplate().start();

```

We Change the background color. This confusing line ensure the background of the 3D scene will be rendered as 0x000000 color, aka black.

```

world.renderer().setClearColorHex( 0x000000, world.renderer().getClearAlpha() );

```

Here we setup the lights of our scene. This is a key factor for the look and feel of your scene. We add a ambient light and 2 directional lights.

```

tQuery.createAmbientLight().addTo(world).color(0x888888);
tQuery.createDirectionalLight().addTo(world).position(+1,+1,1).color(0x88FF88);
tQuery.createDirectionalLight().addTo(world).position(-1,-1, 1).color(0x8888FF);

```

Some constants

First we initialize nBar to store number of bars in our 3D vuemeter. This number MUST be odd, thus the vuemeter is symteric with the middle

```

var nBar    = 41;
console.assert(nBar%2, "nBar MUST be a odd number.")

```

Now we need to compute the width of each 3D bar. The whole vuemeter is 80 wide. So each bar is 80/nBar wide.

```

var barW    = 80/nBar;

```

We create an array bars3d. We will use it to store the object3D for all bars of the histogram.

```

var bars3d  = [];

```

Build the 3D VueMeter

First we create the container group3D which gonna regroup all the bar3D. It is the container of the whole 3D Vuemeter

```

var group3d = tQuery.createObject3D().scale(1/20).addTo(world);

```

We gonna build each bar and add it to group3d. We loop to create nBar with tQuery.createCube(). In fact a bar is a rectangular box, so like a cube with different dimensions. a bar got a width of barW, an height of 10 and a depth of 5. The material is a simple lambert. Once the bar is create, we add it to group3d and set it to the correct position in space. We push every bar3d into bars3d for future reference.

```

for(var i = 0; i < nBar; i++){
    var bar3d   = tQuery.createCube(barW, 10, 5, new THREE.MeshLambertMaterial({
        ambient : 0x888888,
        color   : 0xFFFFFF
    }));
    bar3d.addTo(group3d).position((i-nBar/2)*barW, 0, 0);
    bars3d.push(bar3d);
}

```

Update Vuemeter From Sound Analyser

Here we hook a function to tQuery rendering loop, tQuery.Loop. Thus this function gonna be executed everytime our 3D scene is rendered. if the sound isnt yet loaded, do nothing.

```

world.loop().hook(function(){
    if( sound.isPlayable() === false )  return;

```

build the histogram of the sound based on RealtimeAnalyserNode .getByteFrequencyData()

```

var nBarHalf    = Math.ceil(nBar/2)
var histo   = sound.makeHistogram(nBarHalf);

```

We gonna loop over each bar3D of our vuemeter. We gonna update each of them based on the sound histogram we just computed.

```

bars3d.forEach(function(bar3d, barIdx){

```

We need to determine which value in the histogram match this vuemeter bar. As our vuemeter is symetric, the vuemeter bar on the far left got the same histogram value as the one on the far right. This make this computation a bit confusing.

```

        var histoIdx        = barIdx < nBarHalf ? nBarHalf-1-barIdx : barIdx - nBarHalf;

```

Now we need to compute the height of the vuemeter bar based on histogram value. This is simple scaling from one to the other: vuemeter height === histo height / 256

```

        var height      = histo[histoIdx] / 256;

```

Now that we computed all that, we update the bar3d. We update .scale.y to change its size and .material.color to change its color. The formulas i used "worked for me". Up to you to be creative and find the one that fit your own needs

```

        bar3d.get(0).scale.y    = height*3;
        bar3d.get(0).material.color.setHSV(0.3+height*0.7,1,1)
    });
});

```

Conclusion

So we used webaudio.js to play a sound and analyses in real time. We used this information to change 3D objects based on this analysis. We leveraged tQuery to reach three.js 3D engine. Now you can imagine any visual effect based on sound analysis. The road to winamp effects is open to you :) We got a rather nice looking WebGL output of a 3D Vuemeter in Real Time for only 40 lines of javascript. I love how short code reduces developement time.

That's all folks. Have fun :)

May 08, 2012 08:32 AM

May 04, 2012

Learning Three.js

tQuery plugin for Doom Characters

This post is about tQuery.md2Character plugin: a cool plugin which allow you to easily play with doom characters. You can see a live demo here. I will walk you thru its example. It include a checkerboard for the ground, a fog for the depth, keyboard to move your player and obviously plugins for the MD2 characters (doom formats). We gonna learn how to move doom characters in webgl in only 50lines of javascript!

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="349" src="http://www.youtube.com/embed/BaCEKbWXbfM" width="425"></iframe>

Background knowledge

First what means MD2 ? MD2 is the file format used in the famous Quake II. Many of the monster you love to hate can be found in this format :) You can find md2 models at sitters-electronics or at planet quake.

You can use it easily in three.js thanks to oosmoxiecode He wrote a nice converter from MD2 to three.js json format. He wrote a post about it with plenty of usefull info on the subject. alteredq wrote several cool demos using it.

Let's Get Started

We gonna walk you thru the 50lines of javascript needed make this demo. It is rather simple. It implies tQuery obviously, and various plugins: One for the fog, one for the checkerboard used as ground, one to bind the keyboard and obviously plugins for the MD2 Character itself.

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="420" mozallowfullscreen="mozallowfullscreen" src="http://learningthreejs.com/data/2012-05-04-tquery-md2character-a-plugin-for-doom-characters/examples" webkitallowfullscreen="webkitallowfullscreen" width="100%"> </iframe>

Nice demo no ? You can try it here. Let's code it!

The 3D World

First we initialize the world in 3D. With tQuery.createWorld(), we create a tQuery.World. With .boilerplate(), we setup a boilerplate on this world. A boilerplate is a fast way to get you started on the right foot. It is the learningthreejs boilerplate for three.js With .start(), we start the rendering loop. So from now on, the world scene gonna be rendered periodically, typically 60time per seconds.

```js

var world   = tQuery.createWorld().boilerplate().start();

```

Change the background color. This confusing line ensure the background of the 3D scene will be rendered as 0x000000 color, aka black. We set a black background to give an impression of night.

```js

world.renderer().setClearColorHex( 0x000000, world.renderer().getClearAlpha() );

```

The Lights

Here we setup the lights of our scene. This is important as it determine how your scene looks. We add a ambient light and 2 directional lights. The ambient light is a dark grey, to simulate the lack of light during the night. We setup a directional light in front colored redish.... This is like a setting sun. In the opposite direction, we put another direction light, bluish. This is like the moon. Well this was my rational :)

```js

tQuery.createAmbientLight().addTo(world).color(0x444444);
tQuery.createDirectionalLight().addTo(world).position(-1,1,1).color(0xFF88BB).intensity(3);
tQuery.createDirectionalLight().addTo(world).position( 1,1,-1).color(0x4444FF).intensity(2);

```

The fog

We had a fog to the scene. For that, we use tquery.world.createfog.js plugins. It allows to create the 2 types of fog from three.js : fogexp2 and fog. density is the density of the fog. 0.01 is very light, 0.9 is almost opaque. In general, fogs are a nice visual trick. It is rather cheap to compute and limits the depth of what you see. It is a nice trick to hide the "end of the world" :)

```js

world.addFogExp2({density : 0.1});

```

The Columns

initialize a material

We will apply it to all the columns. It is lambert lighting the ambient is the color which gonna be combined with be combined with the ambient light we initialized on top. color will be combined with the directional lights. and map gives the texture to use.

```js

var material    = new THREE.MeshLambertMaterial({
    ambient : 0xFFFFFF,
    color   : 0xFFAAAA,
    map : THREE.ImageUtils.loadTexture('../../assets/images/water.jpg')
});

```

Build 15 Columns

loop over each column

```js

for(var i = 0; i < 15; i++ ){

```

Create the cylinder. We pass some parameters to the contructor to setup the size we see fit, and we add the material we want to apply on the cylinder. Then we use .addTo() to add our object to our tQuery.World.

```js

    var column  = tQuery.createCylinder(0.2,0.2,2, material).addTo(world);

```

Change the position of the column. We translate the column to build a kind of alley. Thus the character will be able to run inside it :)

```js

    column.translateX(i%2 ? +1 : -1).translateY(1).translateZ(15/2 + -1*i);
}

```

The Ground

We create a large checkerboard with tquery.checkerboard.js plugin. We scale the checkerboard to 100 per 100 units in the 3D world. Thus it is quite large and disappears into the fog. It gives the cheap impression of an infinite checkerboard.

```js

tQuery.createCheckerboard({
    segmentsW   : 100,  // number of segment in width
    segmentsH   : 100   // number of segment in Height
}).addTo(world).scaleBy(100);

```

The Character

We use tQuery.RatamahattaMD2Character plugin. Its inherits from tQuery.MD2Character plugin. All the configuration for this particular character ratamahatta is already done for you. We attach it to tQuery world. Additionnaly we use .hookKeyboard() which bind arrow key to character moving. This function is part of keyboard plugins for ratamahatta

```js

var character   = new tQuery.RatamahattaMD2Character().attach(world).hookKeyboard();

```

Here we show an example of binding the "loaded" event. It is notified once the whole characters data are loaded (texture, mesh for animations of body and weapons). It just display the name of the available animations.

```js

character.bind("loaded", function(){
    console.log("list animmation", Object.keys(character._meshBody.geometry.animations))
});

```

We setup the user camera controls. It will determine how the user camera will move in the world scene. We use tQuery.MD2Character.CameraControls plugin made specially for this case. With it, the camera will follow the MD2 character looking at it from above. world.setCameraControls(new tQuery.MD2Character.CameraControls(character));

Change the Skin by Keyboard

hook a function in the rendering loop. This function will be executed everytime the scene is rendered. Within this function, we will use tQuery.Keyboard plugins to test the keyboard. if the key s is pressed, then use character.setSkin() to change the skin of the character.

```js

world.loop().hook(function(){
    var keyboard    = tQuery.keyboard();    // get keyboard instance
    if( keyboard.pressed("s") ){        // if the key 's' is pressed, change the skin
        character.setSkin(Math.floor(Math.random()*5));
    }
});

```

Conclusion

So we have seen what is possible to do with tquery.md2character and 50lines of javascript. It is a rather short code for what you got on the screen, if you ask me. Btw all that released under MIT license. I think i like the code walkthru format. I find it efficient to describe tQuery examples and fast for me to generate. It is directly derived from annoted doc format as you can see here. I will likely do more in the future.

That's all folks. Have fun :)

May 04, 2012 08:26 AM

May 03, 2012

Learning WebGL

WebGL around the net, 3 May 2012

Wow, now this has been a busy week!

Got a WebGL demo you want me to put in next week’s roundup? Leave a comment below, or drop me a line!

by giles at May 03, 2012 02:12 PM

May 02, 2012

Learning Three.js

Augmented Reality 3D Pong

This post presents a livecoding screencast of Augmented Reality 3D Pong. This is an experiment to use augmented gestures as a way to interact with game. So i picked a game classic "pong". We gonna learn how to code a pong in augmented reality with webgl. The result code is only 100lines!! Nice for augmented reality + webgl + a game :)

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="349" src="http://www.youtube.com/embed/ZTwhHwAHc3c" width="425"></iframe>

But First... What is augmented gestures ? I made augmentedgesture.js. This is a library which use getUserMedia and WebRTC to grab the webcam. It analizes the image with imageprocessing.js and extract the location of flashy balls. I presented it first at Web-5 conference with me punching Doom characters in augmented reality :) 'Doom: a new workout for geek?' on youtube is preview of it. For the webgl, we obviously gonna use three.js and tQuery.

Controllers for the Wii or PS3 did good as game controllers. kinect is super cool obviously. They all requires to buy specific hardware tho... So the money is a barrier. Some even require specific installation on your computer, with code to compile. This is another barrier. With augmented gestures, you dont need specific devices. I like to use objects which are cheap and readily available in our everyday life. Thus people got easily access to the content, in a pure web vibe. I use children toys that i paid 3euro per ball. Another possibility is to use post it. They work well thanks to their flashy colors as you can see in this video. They are available in most offices. Another is to use dish gloves. They are readily available and cheap.

Try it! This screencast is a presentation on how to code augmented reality pong 3D. The code is on github under MIT license. The slides of the presentation are here. Im not sure about the format of this video... the mix live coding + slides + screencast is usual. Anyway publishing it in "publish early, publish often" mood :)

Enjoy

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="349" src="http://www.youtube.com/embed/iunNd5lmAVE" width="425"></iframe>

May 02, 2012 11:38 AM

April 26, 2012

Learning WebGL

WebGL around the net, 26 April 2012

  • The first WebGL Camp Europe has been announced! It’s on 3 July 2012 in Muttenz (near Basel), Switzerland.
  • The mass driver test organised by Benoit Jacob of Mozilla has led to a bunch of fixes going in to Gecko, so if you’re interested in helping again, the second round of tests has now started.
  • Sway is a very neat 4K demo by Bits’n’Bites. (via WebGL.com) [WARNING: Steve reports in the comments that this one "crashes my graphics driver. Using Chrome versions 19 and 20, Windows 7 32-bit, NVidia Geforce 8600m"]
  • Here’s a cool shader-only demo by Simon Green on the GLSL Sandbox, inspired by M.C. Escher’s Depth. (via AlteredQualia)
  • Ludum Dare is a rapid game development community; LittlePlanetBigRocket is a very fun entry into their “Tiny Planets” WebGL competition, from David Evans.
  • Another great demo from AlteredQualia: a car with gorgeous baked illumination. (via WebGL.com)
  • Never mind all this GPU-enabled realism stuff. Let’s render our Three.js scenes in ASCII! (via Tony Parisi)
  • Stewart Hamilton-Arrandale’s Ribbons demo is quite attractive. (via WebGL.com)
  • The Superformula can apparently be used to describe many complex shapes and curves that are found in nature. Here’s a Three.js-based explorer for it, by (I think) Sebastian Sadowski.
  • Jerome Etienne’s Tunnel demo will look familiar to anyone who’s seen the BlackBerry TunnelTilt game — though it doesn’t have the gameplay elements yet. (via WebGL.com)
  • Here’s a nice little fractal terrain generator in Three.js by Xueqiao Xu (via Nooshu on the Three.js subreddit)
  • Kamiori is a site by Aleece Burgess to teach origami using WebGL. (via WebGL.com)
  • Following the Japanese theme, if vocaloid music is your kind of thing then you might like Atsushi Takayama’s Miku Miku Dance. (via WebGL.com)
  • Windows Maze by SirTopHat is quite fun! (via WebGL.com)
  • Gerber files are used to describe printed circuit boards; Mayhew Labs have developed an online viewer for their results. (via Nooshu on the Three.js subreddit)

by giles at April 26, 2012 06:15 PM

April 19, 2012

Learning WebGL

WebGL around the net, 19 April 2012

by giles at April 19, 2012 02:33 PM

April 12, 2012

Learning WebGL

WebGL around the net, 12 April 2012

by giles at April 12, 2012 02:35 PM

Learning Three.js

Video Conference on Top of WebGL

This post presents WebGL Meeting, a very simple WebGL application to do webrtc call. It is a follow up of "Fun with live video on webgl". It was presenting how to use the WebCam using WebRTC getUserMedia(). This one goes one step further and make an actual WebRTC call displayed in a WebGL scene.

In fact, it has already been done a month ago! As you can see here :) The video from the first post, 'being on tv, watching tv' has been answered by Ethan Hugg from cisco. My very first video reponse btw! He shows a SIP video call using an version of Chromium hacked by Suhas Nandakumar. Definitly cool stuff! WebGL Meeting is similar but run on unmodified browsers. The screencast below is short demo of it.

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="349" src="http://www.youtube.com/embed/Fjb7xBnxq9k" width="425"></iframe>

WebRTC progress

Using a modified browser is cool for make nice demo like this one. Nevertheless it reduces how widely the technology can spread. It is now possible to do it using opensource and mainstream browsers. This field advances so fast!

Mozilla team is working hard to make it happen as soon as possible. It is even available on mobile with Opera Mobile 12. Some "protothon" are happening about it. WebRTC is on the edge but it is definitly coming hard. The picture on the right is Chrome WebRTC team doing thumb up on WebGLMeeting at an WebRTC event for IETF 83 :)

What about the code ?

WebGLMeeting source is available on Github under MIT license. It uses three.js to handle the WebGL. It is the AppRTC app mostly unmodified, with a simple WebGL skin on top.

A post from Chrome WebRTC team recently announced "Source code to apprtc.appspot.com example app available". The post releases the source on google code. The apprtc demo is a very simple, one-to-one, webrtc call. Go look at the source, dont be shy :) It is very small, the whole code client+server, is less than 15kbyte. It is easy to understand and deploy thanks too google App Engine.

Face tracker seeking love ?

Surprising hey ? Well the source contains a face tracker, face.html. It works rather well but it is slow. If somebody could give it more love... It is a rather naive implementation which works well but got many rooms for speed improvement. It could make face tracking, less clumsy than wearing augmented reality marker on top of your head like i did a while back :)

Conclusion

I got the feeling WebRTC gonna change a lot of things soon. The peer-to-peer aspect makes it super cheap to integrate live video conferences to your own sites.

That's all folks, have fun!

April 12, 2012 11:20 AM

April 05, 2012

Learning WebGL

WebGL around the net, 5 April 2012

Got a WebGL site you’d like to see in next week’s roundup? Leave a comment below!

by giles at April 05, 2012 01:55 PM

March 29, 2012

Learning WebGL

WebGL around the net, 29 March 2012

Got a WebGL site you’d like to see in next week’s roundup? Leave a comment below!

by giles at March 29, 2012 02:52 PM

March 22, 2012

Learning WebGL

WebGL around the net, 22 March 2012

Got a WebGL site you’d like to see in next week’s roundup? Leave a comment below!

by giles at March 22, 2012 02:45 PM

March 20, 2012

Learning Three.js

tQuery WebAudio for More Realistic 3D

This post is about Web Audio API. It is a new HTML5 api which provide great controls on the audio layer. It is much better than the audio tag. It is more suitable for games or music software. As 3D lovers, the one feature that we care about is audio spacialization. This makes Web Audio a complement to webgl. It implements positional sounds, so you get panning, dopler and all. It makes the scene so much more realistic.

The user tends to associate 3D to reality, so efficient 3D is a lot about realism. The brain identifies 2D as artificial while 3D seems immediatly more natural. Anything which appears close to reality increase this effect. Feeding this illusion creates a more immersive experience to the user. Realistic physics is one (stay tuned :). Web Audio audio spacialization is another.

The screencast below is a live coding session using tQuery.WebAudio. If you want, you can experiment with this code in our playground. Just click here and start coding :)

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="349" src="http://www.youtube.com/embed/QjRF0_KENQ8" width="425"></iframe>

Background on WebAudio API

To learn about WebAudio API is a large subject. It is out of the scope of this introduction. You can refere to many dedicated tutorials tho. The specification itself is clear and very readable.

You can find more comprehensive documentation at html5rocks. It contains several very usefull tutorials to learn Web Audio API. They go from "Getting started with the web audio API" to "mixing positional audio and webgl" or "developing game audio". If you want, you can find demos in chromium samples.

Now let's start coding :)

Let's get Started

First you need to enable WebAudio into your world. Thus you will be able to play sound in it.

```javascript

world.enableWebAudio();

```

Now that the world is able to do sound, let's create one

```javascript

var sound = tQuery.createSound();

```

Now we need to load a sound file and to start playing it. The callback is notified when the file is downloaded. At this point, the sound it ready to play.

```javascript

sound.load('techno.mp3', function(sound){
    sound.play();
});

```

If you want to know more, the full API is documented here and here thanks to jsdoc.

Spacialization and Animation

Now that we can play a sound, what else can we do ? One definitively interesting part for webaudio API is the ability to spacialize the sound. The easiest way to do that is to use .follow() function.

```javascript

sound.follow(object3d);

```

If you want more controls, you can check .updateWithObject3d() or .updateWithMatrix4(). You may want to animate your 3D object based on the sound you hear. For that, a simple function .amplitude() has been written. It is likely a naive implementation but it does the trick, i think.

```javascript

var amplitude = sound.amplitude();

```

It returns an average of low frequencies of the sound. Note that i dunno if it is the proper term in audio world. Most likely not :) If you know the proper term, please leave a comment.

Want more info ?

You get two examples in the source. The minimal one simply play a sound. The other is more interactive. It is the playground. It allows to play with various parameters. tQuery API documentation is provided via jsdoc. You can find the whole API here. The plan is to do the same for the plugins.

So for tQuery WebAudio plugin, you get API documentation of each class: the main class tQuery.WebAudio and the Sound class. You can even check the Node chain builder doc if you want to go deep and configure your own audio nodes chain :)

Conclusion

Ok so now you can play sounds in your 3D scene. You can make the sound follows a given object3d with realistic sound spatialization. All that in just a few lines. Rather cool if you ask me :) Winamp effects are back !! Later i will likely implement click detection as seen here and environmental effect like 'cathedral', 'telephone' etc... as seen here.

I love how sound make our 3D scene more realistic. That's all for today, have fun :)

March 20, 2012 12:08 AM

March 15, 2012

Learning WebGL

WebGL around the net, 15 March 2012

  • Nervous System produce custom jewellery based on cellular designs, and they’ve written a WebGL design tool (apparently based on Processing.js) for it.
  • More fun from OutsideOfSociety: Monster Truck. (via Creative JS)
  • The X Toolkit (as well having a name that sends shivers down the spine of many developers of a certain age) is WebGL framework to visualize medical imaging data and other scientific data.
  • “The purpose of gloc is to make it much easier to build – and much easier to share – shaders”.
  • As everyone knows, cows are the natural enemies of zombies. Yagiz Gurgul proves the point.
  • Anisotropic filtering, which landed in Firefox nightlies a little while back, is now in the Chrome dev channel. Brandon Jones has a good post about it.
  • Also from Brandon, and not strictly WebGL, but if you’re building HTML5 games using some of the new experimental APIs like full-screen display and mouse-locking, you’ll probably find his game shim useful.

by giles at March 15, 2012 07:40 PM

March 12, 2012

Learning Three.js

Augmented Reality in the Browser

This post is about augmented reality in the browser. In a recent post, we saw that it is now possible to have live video in webgl with WebRTC. Due to this, augmented reality is under the spotlight. Recently html5rock published a tutorial by ilmari heikkinen about "writting augmented reality application using jsartoolkit". Ilmari is google devrel for webgl and the author of JSARToolKit too. So we are in good hands :) The tutorial even include a part about binding it with three.js. I took this nice tutorial and packaged the code even easier to reuse.

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="349" src="http://www.youtube.com/embed/rzLuJxTraos" width="425"></iframe>

Try this demo. If you got WebRTC is available in your browser, take this marker, and put it in front on your webcam. It is the same you see on the right. It is best to print it on paper. If you can't, point your phone to this page instead. Phone screens tend to reflect lights from your environment tho. They may reduce the accuracy of the marker detection.

Now let's see how you can to use all this to build your own demos :)

You Include it

First you include it as usual in your page. The code is available here. Note that JSARToolKit is released under GPL, so some restrictions apply. The threex is under MIT license as usual.

```html

<script src="JSARToolKit.js"></script>
<script src="threex.jsartoolkit.js"></script>

```

You Initialize It

Once you get the code, you instanciate the object like this.

```javascript

var threexAR    = new THREEx.JSARToolKit({
    srcElement  : srcElement,
    threshold   : threshold,
    callback    : function(event){}
});

```

The srcElement may be a video, an image or a canvas. When the video is shoot in a uncontrolled environement, the marker detection may be less reliable, due to variations of lighting. threshold is a value between 0 and 255 to adapt your detection to those variations. To detect the augmented reality markers in the srcElement, just use this line in your rendering loop.

```javascript

threexAR.update();

```

No rocket science here.

You Use It

During .update(), the callback is notified with events. They describe the markers present on the srcElement. Each event got various fields: A .markerId which tell you which marker has been recognized. The one used above is the 64. You can find the whole list in JSARToolKit repository.

The .type field describe what is happening to this marker. It may be create, update or delete. create if the marker has just been detected, update if the marker was present before. and delete if the marker is no more present. Rather obvious :) The .matrix field is a THREE.Matrix4. It is a transform which matches the position of the marker in space.

Conclusion

So now we can do augmented reality in a browser. The code of the demo is here. Up to us to find actual application of this technology. Currently most browsers with webcam are running on desktop/laptop tho. As most their webcam is directly attached to screens, It limits the flexibility of what you could put on front of the camera. As for mobile, only opera 12 is currently the only mobile browser able to read the webcam.

That's all folks. Have fun :)

March 12, 2012 10:36 AM

March 08, 2012

Learning WebGL

WebGL around the net, 8 March 2012

  • This looks incredibly cool: Ilmari Heikkinen has written an article on how to use the JSARToolKit library with the WebRTC getUserMedia API (which allows you to access the browser’s webcam) to put “a 3D model on top of an augmented reality marker in webcam video” — basically, augmented reality in a web page. Looks like it only works in the Chrome dev channel right now.
  • Another webcam/WebGL demo — this one works in Opera Mobile 12 on Android, though! Paul Neave’s WebCam Toy. (via Mr. doob)
  • Chris Dalton has ported Shatterquest, an old OpenGL ES game, to WebGL.
  • From Ryan Alexander, an project from last week’s Art Hack weekend: Audio Shadertoy, an easy way to experiment with shaders that react to music. Live version here.
  • A visualisation of wind motion patterns across the US, by Nicolas Garcia Belmonte.
  • Naturally, if you’re creating a texture, then the best test model to try it out on is a skull: Deathpaint, from Johnny Slack at Cartelle Interactive. He’s also put together some notes on how and why it was created. (via Einar Öberg)
  • Boot to Gecko is Mozilla’s new operating system, designed “to pursue the goal of building a complete, standalone operating system for the open web”. Basically, the aim is to make web applications running on it using open web standards as capable as apps on other OSes — for example, iOS or Android. This would also benefit web apps running on other platforms, as they’d have access to the same APIs. The WebGL connection is pretty clear, and here’s a video of a nice example of how far they’ve got with that — this video shows BtG running on a Samsung Galaxy S II, and (from about 1m30) shows a WebGL demo running apparently at about 30fps. (via AlteredQualia)
  • Coming soon in WebGL: anisotropic filtering, a technique for improving textures on surfaces (more about this on Wikipedia). It’s in Firefox nightly builds now for non Windows platforms thanks to Florian Boesch, and is going in to WebKit. There’s a demo here. (via Benoit Jacob)
  • Noma Racer is the beginnings of a car-racing game from György Pesti of Nomo Solutions.
  • Another WebGL/Kinect demo, this one from Mr. doob. (via WebGL.com)
  • A demo I’d not seen before, from Spacegoo: a planetary system (also via WebGL.com)
  • By Sann-Remy Chea: Terrain generation: the diamond-square algorithm and Three.js
  • An interesting result from the HTML5 + WebGL Hackathon last weekend: some flying toasters (that will look familiar to anyone who used Macs a few decades back…), by Will Eastcott.
  • From Victor Martins, some nice demos of subsurface scattering (via WebGL.com)
  • Inka3D is a tool for exporting Maya content for use in WebGL apps; here’s a simple tutorial.

by giles at March 08, 2012 03:15 PM

March 05, 2012

Learning Three.js

tQuery v0 - Let's get started

This post is an update on tquery progress. Our previous posts were previews, for example valentine card in tQuery or linkify, a tQuery extension. This post is the release of version 0. It will walk you thru the website and shows how to run your first tQuery project with the boilerplate. You should be able to play with tQuery after that :)

Ok It is still experimental. I have been paddling hard to make it usable by other people tho. The playground is the easiest way to start experimenting. It is all online. no install, no download, simple and understandable. tQuery code is all on github repository. The screencast below will walk you thru the website.

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="349" src="http://www.youtube.com/embed/iby6kijX5Zw" width="425"></iframe>

Solid Ground to Build On

I would like tQuery to be a solid ground. Thus people can easily build their three.js extensions on top of it. So the code is documented, tested and performance is monitored. Here is some principles that i consider important for tQuery. Note that those principles are the theory. It doesnt imply i implement them well in practice :)

Code must be tested. It helps detect bugs earlier. Our tests are done with mocha. API must be documented. It helps new users to use the library. API documentation is done with jsdoc. Performance must be monitored. Thus developpers are immediatly aware of performance change when the code is modified. Our benchmarks are done with benchmark.js and displayed by benchrunner.

How to Get Started

or how to get the boilerplate :) tQuery Boilerplate is a template to get you started. You download it and modify it until it fits your needs. It is a fast way to start a clean project with tquery. The running boilerplate looks like that. The screencast below shows how to use it.

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="349" src="http://www.youtube.com/embed/YOsnKMesyRk" width="425"></iframe>

Running tQuery Boilerplate

You can try the boilerplate online with the playground. Want to run it on your computer ? First you get boilerplate's files here. Then you launch the http server to serve them. Here is a little shell script which does it all for you.

```bash

curl -OL https://github.com/downloads/jeromeetienne/tquery/tqueryboilerplate.zip
unzip tqueryboilerplate.zip
cd tqueryboilerplate
make server

```

Then you open a browser on http://127.0.0.1:8000/ to see it running. Up to you to modify index.html until it fits your needs. index.html looks like the code below... Quite short.

```html

<!doctype html><title>Minimal tQuery Page</title>
<script src="./tquery-all.js"></script>
<body><script>
    var world   = tQuery.createWorld().boilerplate().start();
    var object  = tQuery.createTorus().addTo(world);
</script></body>

```

Conclusion

This is the initial release of tQuery. I like how it looks. API is documented, code is tested, and performance measured. The code produced by the API seems short and quite understandable. Nice foundations especially for a version 0.

The next step is about stabilizing tquery.js itself, cleaning it up. I am currently quite busy doing just that. So please dont hammer me with feature requests at the moment, i won't have time to handle them. Pull requests are welcomed tho. Things will change when tQuery core become more stable.

That's all folks, have fun :)

March 05, 2012 09:42 AM

March 02, 2012

hacks.mozilla.org

Friday fun: Trigger Rally in WebGL

As reported by Creative JS, Jasmine Kent ported her open source Linux racing game Trigger Rally to WebGL to run in HTML5 browsers. In the following video you can see it running pretty smoothly on my MacBook air that is already running 12% of CPU without it starting (as ScreenFlow is recording and VLC was playing music whilst TweetDeck used quite a chunk, too):

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="315" src="http://www.youtube.com/embed/M31heMqQ0Ug?rel=0" width="500"></iframe>

If you are the artistic type, you can even design your own levels for the game.

You can play play Trigger Rally online here: http://triggerrally.com/ or follow it on Twitter @triggerrally.

by Chris Heilmann at March 02, 2012 03:58 PM

March 01, 2012

Learning WebGL

WebGL around the net, 1 March 2012

by giles at March 01, 2012 02:35 PM

February 27, 2012

Learning Three.js

Linkify, a tQuery Extension

This post is an update on tquery progress. It is about linkify, a first experimental extension. Thanks to it, any 3D object may become a link. So 3D objects act as a <a> tag, i.e. the object becomes clickable and clicking on it open a new url. It is built on top of domEvents. It is used to incoporate dom kindof events in 3D world. We saw them a few week back in 'dom events in 3D space' post. Previous posts on tquery may be found here.

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="349" src="http://www.youtube.com/embed/MlW7PeuXGDM" width="425"></iframe>

Building extensions on top of others is kinda the point of an extension system. My dream scenario is : (1) People do plugins for three.js, like they do in jQuery). (2) They share their work. (3) They build on top of each other. (4) Loop to 1. All in opensource spirit. All good in my book. Ok enougth talk, let's code.

Dom Events in 3D Space

domEvents have been ported to tQuery. It is an important part because jQuery developpers use this a lot, thru .on()/.off().

```javascript

tQuery('cube').on('mouseover', function(event){
    console.log("somebody put the mouse over a cube");
});

```

The supported events are click obviously, dblclick, mouseup, mousedown , mouseover and mouseout. It has been improved to better match actual dom events. The callback now receives a event object. It contains .type and .target as described in dom specification.

```javascript

tQuery('.myClass').on('click', function(event){
    console.log("An event of type", event.type, "has been trigger on ", event.target);
    // If you wish to stop propagation, just do 
    event.stopPropagation();
});

```

Event bubbling is now supported. So events are dispatched to the target and follow its parent chain upward. It is possible to cancel propagation with an usual .stopPropagation().

Linkify or How Any 3D Object May Become a Link

Linkify is an experimental plugins built on top of tquery.domevent. It is shown in the screencast. It makes any 3D objects object act as a <a> tag, i.e. the object becomes clickable and clicking on it open a new url. When the mouse is over it, an underline is added to make it even more webpage like. Code is rather short.

```javascript

tQuery('text').linkify('http://example.com')

```

Conclusion

It has been quite time consuming to set up the basis for the project: tests, bechmarks, docs, or plugins interdependancy resolution. For each of those field, i had to review the various alternatives, pick one and setting it up as properly as possible.

Here are the current choises, they may change in the future. require.js will be used for the dependancies between plugins. Tests are done with mocha, a javascript test framework for javascript which run in node.js and browser. Later, we may improve that by testing the rendering output using pixastic to do statistical images comparison. Benchmarks are done with benchmarks.js, a robust benchmarking library for javascript, using benchrunner as runner. It is the engine behind the wellknown jsperf site. Inline documentation is written in jsdoc format using codeview template.

That's all folks. Have fun :)

February 27, 2012 07:55 AM

February 23, 2012

Learning WebGL

WebGL around the net, 23 February 2012

  • Bytebeat music is generated by simple functions — a complete tune in just a few lines of formulae. Gregg Tavares has created an HTML5 bytebeat editor, with a new WebGL-based visualiser.
  • A lovely cloth simulation from Kamibu.
  • Fun stuff: Trigger Rally.
  • p3d.in is a site where you can share your 3D models, and it’s just entered public beta.
  • Interesting: Lively3D is three dimensional windowing environment, based on GLGE. Here’s the release announcement.
  • Another fun demo from AlteredQualia: WebGL pasta.
  • A cool Three.js demo with explanation from Thibaut Despoulain: animated selective glow.
  • Looks like this could be an interesting series: Let’s Make a 3D Game with HTML5.
  • A blog post from Cedric Pinson on the making of the surreal Nouvelle Vague demo.
  • BlackBerry have released version 2.0 of their PlayBook operating system; among its new features is one we heard about last year: WebGL support, not (I think [UPDATE: confirms]) for web apps per se, but instead for applications that have been built using HTML5 technologies for their application platform.
  • Brandon Jones has polished up his Quake 3 demo a bit: “(JQuery is gone, updated glMatrix, started on a more generalized mouselock/fullscreen shim, etc) and there are parts of it that should go a little bit faster, but the most visible change is that I’ve got some really REALLY basic gamepad support!” Here’s his Google+ post about it. (h/t Mariuz)
  • Web3D is a conference co-located with SIGGRAPH this August, “focused on new 3D Web and Multimedia technologies” including WebGL.

by giles at February 23, 2012 03:31 PM

February 16, 2012

Learning WebGL

WebGL around the net, 16 February 2012

It’s been a busy week!

by giles at February 16, 2012 02:37 PM

February 15, 2012

Learning Three.js

a Valentine card in tQuery

The tQuery experimentation is going on. It is a lot of fun to code :) This post is just a short presentation of two plugins currently in incubation: tquery.text and tquery.shape. Yesterday was valentine day, so i thought it would be cool to stay in topic. The screencast is a live coding of a valentine card in tQuery :)

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="349" src="http://www.youtube.com/embed/8EHqrAXcKrY" width="425"></iframe>

Let's Write Text in 3D

tQuery.text plugin writes text in 3D. It is based on TextGeometry. Here is a simple example.

```javascript

tQuery.createText("tQuery is Fun!").addTo(world);

```

Let's Easily Create Shape

tQuery shape is made to easily build and extrude shapes in javascript. It is based on THREE.Shape. tquery.shape is cool because it uses a API very similar to canvas 2D path. This line will build a triangle.

```javascript

tQuery.createShape().moveTo(0,0).lineTo(1,1).lineTo(-1,1).lineTo(0,0);

```

Some shapes are already available, like the triangle above, or a fish, smiley and a heart. Here is a smiley.

```javascript

var shape = tQuery.createSmileyShape();

```

The valentince card

Last but not least, the valentine card! Try it out! It uses the plugins above to build an animated valentine card. It is done with less than 20lines... tQuery seems to produce short code.

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="349" mozallowfullscreen="mozallowfullscreen" src="http://learningthreejs.com/data/2012-02-15-valentine-card-in-tquery/" webkitallowfullscreen="webkitallowfullscreen" width="100%"> </iframe>

Conclusion

Today we saw 2 plugins still in progress. tQuery experiment seems to go well for now. The code is moving at fast pace. I am currently experimenting with require.js to automatically resolve dependancies between plugins. What's next ? likely a series with a step by step on how to build a tunnel game.

That's all folks! have fun :)

February 15, 2012 09:21 AM

February 09, 2012

Learning WebGL

WebGL around the net, 9 February 2012

Gosh, it’s been a while! The link backlog got out of control over January, so I’ve had to declare link bankruptcy… so here’s the stuff I’ve heard about over email since then, new stuff coming next week.

by giles at February 09, 2012 03:15 PM

February 08, 2012

Learning Three.js

An Extension System for three.js

This post an overview of a work-in-progress. It is about an extension system on top of three.js which mimics jQuery API. I came up with the idea while thinking about how to trim three.js and make it easier to maintain. I have always been impressed with jQuery plugin ecosystem. It is lively, varied, and contains impressive specimens. I would love to have such a rich ecosystem for three.js's plugins.

Let's call this experiment tQuery as in "three.js + jQuery". It makes it easier to understand if you already known this library. This is a v0 in the "publish early, publish often" vibe. The goal of this little project is to see if we can mix to mix three.js power with jquery API usability... How far this concept can fly ? We will see.

So what do we want ? The code must make three.js easy to extend and should mimics jQuery whenever possible. In order to see if the system hold under load, i wrote several extensions already. It is very early. The architecture of it all is far from stable. Code is advancing at fast pace tho :) The screencast below is short live coding session. Just to give an idea of the current status.

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="349" src="http://www.youtube.com/embed/Aa7sHUE224A" width="425"></iframe>

DOM

With jQuery and the DOM, you get a tree of elements from the page. In fact, three.js got this tree as well. Surprising hey ? We just name it a scene instead of a tree. And our element are called Object3D. But all that is just a matter of vocabulary.

One one hand, jquery one, you got the dom and its tree of element. on the other hand, three.js one, you got the scene and its tree of object3D. Same Thing!

Chained API

jQuery got a chained API, so tQuery got a chained API. When we said copy jQuery whenever possible, we were not kidding :)

```javascript

tQuery('.fooKlass').scale(2).translate(1,0,0);

```

IDs and classes

They got Ids and classes , or more recently data. So we did all the same with tQuery.

```javascript

var cube    = tQuery().createCube();
cube.id("myId");    // set the id of this element
cube.addClass('fooKlass');  // add 'fooKlass' class to this cube
cube.data('goom', 'baa');

```

Selector

jQuery got selectors so tQuery got selectors too. Here are the selector based on geometry, they are similar to the [element selector] in jQuery, e.g. jQuery('span').

```javascript

tQuery('sphere');   // select all objects with a sphere gemotry
tQuery('cube'); // smae with a cube gemotry
// and so on

```

Here are the one for classes and id. Note how the syntax is similar to css selector.

```javascript

tQuery('#myId') // to get the object with the 'myId' id
tQuery('.fooklass') // to get objects with the class 'fooklass'

```

obvious we got compose them like with jQuery

```javascript

tQuery('.bar.foo')  // objets with the class 'bar' and 'foo'
tQuery('.bar cube') // objets with the class 'bar' with a cube as descandant

```

Events

Obviously jQuery got events, so we got events in tQuery. we use domEvents we saw a few week back in 'dom events in 3D space' post

```javascript

tQuery('cube').on('mouseover', function(){
    console.log("somebody put the mouse over a cube");
});

```

A Basic Page

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="280" mozallowfullscreen="mozallowfullscreen" src="http://jeromeetienne.github.com/tquery/plugins/minimal/examples" style="float: right; margin-left: 1em;" webkitallowfullscreen="webkitallowfullscreen" width="260"> </iframe>

This is a minimal page. the code is below, the preview on the right. Quite short.

```html

<!doctype html><title>tQuery Basic Page</title>
<script src="tquery-bundle.js"></script>
<body>
    <script>

    var world = tQuery.createWorld().fullpage().start();
    var object = tQuery.createTorus().addTo(world);

    </script>
</body>

```

Conclusion

This was early presentation of tQuery. I like the idea, we will see how it goes. The purpose of this experiement is to help those who know jQuery to use three.js. So they reuse jquery syntax but inside a webgl context. This is a very early project. How far is it possible to push this concept of "three.js power + jQuery API usuability". It seems all very cute at first sight but only time will tell.

That's all folks. More on tQuery soon. Have fun :)

February 08, 2012 02:24 PM

February 07, 2012

Learning Three.js

Fun With Live Video in WebGL

This post is about live video in webgl. It is possible in today browsers to read the webcam using a new feature from html5, called WebRTC. This standard is about real-time communications such video conferences. It is an open source project supported by Google, Mozilla and Opera. Quite neat hey!

I think live video has a lot of potential usages in 3D. It is so cool for interactivity. The player sees himself on the screen. It becomes part of the actions. Quite immersive effect. We can imagine something like second life, where people wander around and interact live with each other in a virtual world. Our demo is about TV... Another obvious use may be reflections like mirror or water. What about your face from the webcam reflecting in water with animated waves ? Would be nice!

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="349" src="http://www.youtube.com/embed/vnNihxl3taE" width="425"></iframe>

It is surely nice but WebRTC is still quite on the edge. To enable webrtc on your computer, see how to run webrtc demos. It is currently available only in Canari. Mozilla people are working hard to make it happen as soon as possible. So it may be too early to use it for 'serious' things. But way enougth to do cool experiments like the one we gonna do today :)

Try it out!! The first step will be to create a video element. We gonna start to make it play either a normal video file then to play video from the webcam using mediastream API. After that, we gonna map this video to a normal texture. And we will be done ! It is that simple, now let's get started.

Let's create the video element

The video element is the DOM way to handle video in webpage. Let's create the video element. Later we will use it as texture and display it in WebGL.

```javascript

video       = document.createElement('video');
video.width = 320;
video.height    = 240;
video.autoplay  = true;

```

It you wish to create a video from a file webm, mp4 or ogv, just set its .src property.

```javascript

video.src = "http://example.com/supercatvideo.webm";

```

It wasn't too hard, hey :) So now we know how to get a video from a file. Let's see if we can use the webcam and get this nice immersive effect for our users.

Let's Use the Webcam if Available

Our first step is to detect if the media stream API is available. The following line will do the job nicely. hasUserMedia will be true if it is available, false otherwise.

```javascript

var hasUserMedia = navigator.webkitGetUserMedia ? true : false;

```

If it isn't, you may point the users to this doc on how to get it and/or using a normal video file. Now we need to check if we can read the webcam. For that, we use the following lines.

```javascript

navigator.webkitGetUserMedia('video', function(stream){
    video.src   = webkitURL.createObjectURL(stream);
}, function(error){
    console.log("Failed to get a stream due to", error);
});

```

A pseudo URL will be created by .createObjectURL. It would allows the video element to automagically read the webcam. It looks a bit like that.

```

blob:http%3A//learningthreejs.com/e33eb278-08a8-4052-9dca-3c7663c88bc0

```

Handle the textures

Now we got the video element ready. Let's create a texture using it as source. The last step before seeing the video moving on screen :) Use this simple line. It is enougth.

```javascript

var videoTexture = new THREE.Texture( video );

```

This texture is a normal texture and can be used as usual in materials. For example, in a lambert material.

```javascript

var material    = new THREE.MeshLambertMaterial({
    map : videoTexture
});

```

But this texture is special, it is a video. So it need to be constantly updated. In your render loop, add those lines. They monitor the state of your video. Every time the video got enougth data to be display, the texture is updated and sent to the GPU.

```javascript

if( video.readyState === video.HAVE_ENOUGH_DATA ){
    videoTexture.needsUpdate = true;
}

```

Conclusion

Now you can display your webcam inside your webgl !! This is simple and cool. Browser support will increase with time. Live video is a very powerfull tool. The image from the webcam is a normal one. On it, you can perform post processing, edge detection, and many other crazy things. Up to you to experiment. Let's all for today folks, have fun :)

February 07, 2012 12:41 PM

January 20, 2012

Learning Three.js

Casting Shadows

This post is about shadow casting, a technique which approximates the effect you see in real life everyday. They may be tricky to tune but they looks so good, it worths it. Shadows are an efficient tool when you to make your scene more realistic. We will see how they can be used inside three.js and see more about lights while we are at it.

As usual, there is a demo. It is kept it real simple thus you can read the code more easily. The scene is a simple object in the middle, a spotlight moving around and a plane to receive the object shadow. The light frustum is left visible in orange.

<iframe allowfullscreen="allowfullscreen" frameborder="0" height="420" mozallowfullscreen="mozallowfullscreen" src="http://learningthreejs.com/data/casting-shadows" webkitallowfullscreen="webkitallowfullscreen" width="100%"> </iframe>

Let's Code Shadows

Casting shadows in three.js involves 3 parts: the renderer which does the computation, the lights which cast shadows, and objects which receives lights and shadows.

Set up the Renderer

The renderer is the one which will compute the shadows positions for your 3D scene. Shadow casting is quite expensive. It is only supported by WebGLRenderer. It uses Shadow mapping, a technique specific to WebGL, performed directly on the GPU.

```javascript

renderer.shadowMapEnabled = true;

```

You can smooth produced shadows with shadowMapSoft. It default to false. On the left, the shadow is crisp, on the right it is soft.

```javascript

// to antialias the shadow
renderer.shadowMapSoft = true;

```

Configure your objects

For Object3D, two parameters controls how they interact with lights and shadows. Set .castShadow to true if the object occludes light, so to cast a shadow. Set .receiveShadow to true if the object is supposed to receive shadows. Both default to false

```javascript

object3d.castShadow = true;
object3d.receiveShadow  = false;

```

This is the configuration for the central object in the demo. It will occlude lights but won't be able to receive shadow. So you wont see any self shadow.

Tune your Lights

THREE.DirectionalLight or THREE.SpotLight are able to cast shadows. Let's details them. A directional light is when light rays are parallel. A bit like when you look at the sun rays on the left. It mostly behaves like a light source very far from us. A spot light is when light rays seems to originate from a single point, and spreads outward in a coned direction, like in the dance club on the right (Images are from wikipedia). To enable the shadow casting on a light, just use this line.

```javascript

light.castShadow = true;

```

You can tune the shadowDarkness. It is the opacity of the shadow. 0 means no shadow, 1 means pure back shadow.

```javascript

light.shadowDarkness = 0.5;

```

In the same vibe, it possible to show the shadow camera on the screen with shadowCameraVisible. A very usefull feature during tuning or debugging.

```javascript

light.shadowCameraVisible = true;

```

More of Directional Lights

Additionally, when casting shadow with a THREE.DirectionalLight, you need to setup an orthographic camera. What is that ? it is a different form of 3D projection. Perspective is the way we see things in real life. So it seems more natural to us than orthographic projection. On the left, an illustration shows a perspective projection. You can see what is inside the orange shape. On the right, the same for a orthographic one.

Recent three.js r47 release includes a very didactic example from alteredq. Play with it, it may understand the difference between orthographic and perspective cameras. Here is a possible configuration of the frustum for the orthographic camera of our light.

```javascript

light.shadowCameraRight     =  5;
light.shadowCameraLeft      = -5;
light.shadowCameraTop       =  5;
light.shadowCameraBottom    = -5;

```

Conclusion

This is it, you can code shadow casting in three.js now :) Go ahead and play with them. They are hard to master but very efficient visually. Keep in mind that those shadows aren't real. They only uses 'some tricks' to make them appears as real. And they do so in real time !! To achieve this result, they take significant shortcuts which produce artifacts. To avoid those require tuning and experience.

That's all for today folks. Have fun.

January 20, 2012 01:44 PM