I have always found myself wanting to play around with 3D ever since Flash’s 10.0 player release gave us 2.5 3D but up till now I have only ever managed to skim the surface. So I figured it was time to delve deeper, and with the HTML5 buzzword being thrown around more than ever, Three.js seemed like the perfect option.
And with a little elbow grease and a lot of spit shine CubeWall, the 3D Image Gallery was created.
Three.js has encompassed many built in helpers for some of the more common 3D shapes, textures and collision detection. All helping you speed up your development time letting you concentrate on what’s important, your creative idea.
Like most 3D libraries there are a few things you need to set up before you can get started. This generally tends to be the scene, the camera and the renderer. To find out how to set up your scene quickly, check out the Three.js site.
Three.js provides many different cameras, scenes and renderers so make sure you play around with a few of them to find out which one works best for you. You will find that they all have different attributes which give you various options when displaying objects in the 3D world.
If you have any problems, don’t fear! The Three.js community is quite large and a little Google time will be sure to answer any questions you might have. If not, don’t be scared to post your question on stackoverflow as it will undoubtedly be answered quickly.
CubeWall in the making
The CubeWall image gallery is pretty basic in interaction and design. It simply loads in predefined images, converts them into Three.js textures, creates new materials using those textures then applies those materials to Three,js Cube Geometry Mesh’s, creating a kind of 3D Cube grid of thumbnails.
As the images are loaded into the gallery they are also resized maintaining their aspect ratio in order to fit the grid view and not distort the image.
Materials are also then sliced based on grid dimensions populating a sliced materials array, enabling a square slice to be created for each section of the grid. If the slice is out of the texture’s bounds, a plain Three.MeshBasicMaterial is created instead.
When a swipe is detected each cube is then assigned a new material from the sliced materials array, based on its location within the grid. Next it swaps out one of its face materials with the new material to show its slice of the enlarged image. Finally, to revert to its original state each cube just swaps its face back to its original material.
So that’s the basic mechanics behind it. I will write another article to further explain the various components I created while making CubeWall what it is today. In the meantime I encourage you to delve a little deeper into the code to get a better understanding of how it all put together.
Cache me if you can…
Creating and using a large amount of textures can have a massive impact on your framerate, this is where caching comes into it’s own. Jerome Etienne has written a great article on how to use caching with three.js, which dramatically improves performance. So instead of force feeding your renderer in small irregular chunks it may be better to have all your data chewed up and digested before proceeding.
So if you find yourself creating a game or even an application that seems to be draining your renderer’s framerate, I suggest you try a little caching before rewiring your application in an attempt to optimize it.
OOPS no you didn’t..!
Initially I had intended to create CubeWall for mobile, hence the swipe interaction to reveal an image. Unfortunately most mobile browsers can only support the Canvas Renderer at this time, which is a lot slower and seemed to have strange performance quirks that I didn’t have time to rectify.
So if you are building for mobile or even different browsers, make sure you firstly determine the supported Renderer, and secondly test your application using the correct renderer. Otherwise your meshes could end up changing from a beautiful masterpiece to smudges of paint smeared on with a stick.
You may also find that CubeWall is a little slow here and there as its not fully optimized yet and at the moment the view loads while the textures are still being sliced, this is something I will work on changing in future.