Spiria logo.

How to Create a 3D Animation Without Model, with WebGL and Three.js

January 26, 2016.

When I was told that my next project would involve WebGL, I did some research. I discovered that all I needed to do was add an HTML canvas to our Web page and delegate the rendering to OpenGL to take advantage of any available hardware acceleration. JavaScript enables interaction with the rendering surface. I decided to look into the three.js project, which has garnered rave reviews.

Having checked out all of the demos and performed a few tests, I needed a subject that would lend itself to an actual project. It just so happened that in the office next door, our design team was putting the finishing touches on our new company logo. Perfect!

The project

The challenge was to build an interactive 3D animation of our logo based on a scatter graph. The project was straightforward, yet complex enough to give me experience with the technology, visually interesting and, who knows, might even be useful for our Web site.

The Model

I already had a logo, but to obtain a 3D version, I needed a model. Three.js supports, among other things, imported Collada models, but upon closer inspection, I concluded that I could probably get away with just an image.

decorative

The logo has white and black elements. By loading the image on a canvas that is invisible to the browser, I can access the pixels. This image will never be featured on the Web site; it merely contains the data needed to make a model.

var im = document.getElementById('logo');

var canvas = document.getElementById('canvas');

canvas = getContext('2d').drawImage(im, 0, 0, im.width, im.height);

var data = canvas.getContext('2d').getImageData(0, 0, im.width, im.height).data;

Now, it is simply a matter of keeping the black elements as valid positions while testing the red component of the rgba (4 values per pixel, starting with red).

var x=0;

var y=0;

for (var i=0; i<data.length; i+=4){

    // if red is lower than 16, it’s black

    if(data[i] < 16) {    

        blacks.push([x,y]);

    }

    if(++x == im.width) {

        x=0;

        y++;

    }

};

Now I can generate points on the front and back faces of the logo model. By limiting the z value (depth) to two fixed values, here is the view you get from a 45-degree angle:

decorative

Now let’s work on the sides. The sides of the model, from an image point of view, are at the border between black and white. How can we get their coordinates? Let’s just apply a translucent Gaussian blur and add a new color: if the pixel is grey, that means we have a valid position for the particles that make up the sides.

decorative

Using random depth values (situated between the Z value of the front and back faces), this is what we get:

decorative

Now, all you have to do is to integrate it in the three.js “points/sprites” example, make a couple of adjustments and slide the canvas under the site content.

How about you? What have you created with WebGL?