Pan and zoom around our WebGL 3D fish tank

View demo

About FishGL

Internet Explorer has a fun history with fish aquariums. Back in 2011, when we announced the launch of IE9, we released an HTML5 performance benchmarking site featuring a fishbowl designed to demonstrate hardware accelerated 2D canvas. For IE10, the fish moved to a brand new tank with more options for experimentation. Fast forward to 2014 and to celebrate WebGL in IE11 we’ve created FishGL, a new 3D fish tank experience. What better way to mark how far the web has come in three years!

The evolution of the web is best told through simple (and fun) concepts. FishGL and its predecessors are just another step in Internet Explorer’s long history in helping push the limits of what’s possible on the web. Today, rich 3D experiences are now possible on the web—blurring the lines between native and web even more. And developers can be confident that WebGL is stable and ready for mainstream use.

Given our previous version of the fishbowl, and other fish related demoes online, we wanted to create a graphics showcase that developers and enthusiasts alike would love (and compare how many fish their devices can run). But the web today can be more than rich and 3D—through multi-touch, it can also be interactive and personal.

How it works

3D on the Web

WebGL is a low level API for rendering 3D graphics. FishGL uses the popular open source library Three.js, which makes it easy to build complex 3D sites using WebGL. There are a few high level steps to create a 3D experience:

  • Create a scene. Think of the scene as a container for whatever you want the camera to see—if it’s in the scene, it’ll be rendered (drawn). In this case, it’s the Ocean Explorer room containing the fish, the tank and other elements in the room.

  • Add a renderer. A renderer draws whatever is in the scene to the screen from the perspective of the camera.

  • Place the objects in the scene. Any item in the renderer that you want to display. In other words, it’s the fish!

  • Use a camera. Cameras convey the scene and objects to the user.

Three.js supports multiple renderers and cameras which can be selected and adapted for your scenario. For example, in this demo, we’ve used a PerspectiveCamera to allow the user to switch from being outside the tank looking in with a normal "field of view", to being inside the tank where the field of view is much wider to simulate a fish-eye effect. Below is the Ocean Explorer Room with the camera set outside with a normal field of view.


Meshes and Materials

FishGL takes you inside the captain’s room on the Ocean Explorer. It’s like a scene from an animated movie. In the center of the room, are the crew’s favorite traveling companions—tropical fish. The fish along with every other object in the room are custom 3D objects. These objects were created by a 3D designer and are better known as meshes. Meshes are simply a set of triangles, or polygons, organized in a way that represents a true 3D object. The more polygons you add to the mesh, the smoother and more defined the object will appear, but at a cost to the speed of your presentation of course. Meshes cannot be seen without materials, and Three makes using materials and shaders very easy. We also created some custom shaders for effects like water animation, tank algae, color tint and underwater distortion.

The 3D fish created for this project use what we call a texture or “color” map. The image below shows 2 different color maps used to apply to the fish in the tank. Not only do they provide color, but notice the attention to shading (and some ambient occlusion).


Without the attention to shading, items in a 3D scene can look very stale and flat rather than inviting and robust. Lights can help, but they only provide shading—not shadows. Meaning, lights will only affect how much light each triangle gets and this helps the human eye perceive the dimensions and details of the model. A good color map with some shadows can also convey features that are not present in the model like scales on the fish.

Animating Models

To bring the tank to life, many of the 3D models need animation. Each 3D fish has logic that enables it to navigate inside the tank, avoid obstacles, and eat fish food. The bubbles floating out of the treasure chest are another fun example of how animation can bring a scene to life. The bubbles were created using a particle system, which manages animation of related set of models. In the following code, we’ll create the material used for each bubble and initialize the particle system:

var material = new THREE.ParticleSystemMaterial({ 
   size: this.size, 
   sizeAttenuation: true, 
   map: app.assetManager.getObjectByName("bubble").texture, 
   transparent: true,
   opacity: 1,
   blending: THREE.AdditiveBlending
   var particles = new THREE.ParticleSystem(geometry, material);

Once we have create the particle system, we can animate the bubbles. When watching the animation, you’ll notice that the bubbles have an elasticity like real bubbles making their way through the water to the top. For that effect we used a cosine function to “ping pong” the scale of the bubble in and out:

// parameters to fine tune bubble movement
var counter = 0, 
    counterStep = 0.75, 
    flexScale = 0.01, 
    calc = 0, 
    elasticity = 0;
function animateBubbles() {
    // adjust size of material so bubbles appear to wobble
    calc = Math.cos(counter); 
    elasticity = calc * flexScale; 
    material.size += elasticity; 
    counter += counterStep; 
    // update vertex positions
    var verts = particles.geometry.vertices,
        i, len, vert;
    for (i = 0, len = verts.length - 1; i< len; i++) {
        vert = verts[i];  
        vert.y += riseStep; 
        // restart bubbles once they hit the top of the tank
        if (vert.y> = topOfScreen) {
            vert.y = origin.position.y;
    // tell renderer that bubbles have been updated
    particles.geometry.verticesNeedUpdate = true; 


You can use the power of WebGL with libraries like Three.js to create complex scenes and scenarios like the fish tank. Three.js has a familiar 3D API that abstracts away many of the low level details so can focus on what makes your site great. It also makes it easy to create custom objects and shaders where you need something unique. Internet Explorer 11 uses the GPU to hardware accelerate graphics, so you can count on it to perform well, look beautiful, and delight your users!

About this demo


Last updated

Sep 8, 2015