Submarine

front-side view of submarine back view of submarine

The submarine is made of several lathe, extrude, and basic torus geometries, with Lambert material for the submarine body and Phong materials for the reflective windows and metal elements. The user can alter its position in the scene using the WASD and IK keys.

Manta Ray

front-top view of manta ray back-top view of manta ray

The manta rays are made of a few reflected Bezier surfaces for the body and wings, a basic cone geometry for the tail, and Katherine Kjeer's TubeRadialGeometry for the lobes. Lambert material is used throughout since rays are not particularly shiny. The user can determine how many rays are generated to accomodate for different GPU capabalities. The rays' position and color are randomly generated throughout the scene given a number of rays and within certain aesthetic ranges. The HSL colors are restricted to generally be blue-green and the positions are generated so that no ray is placed too close to another.

Scene

scene with no objects
texture for ocean surface
Texture used for ocean surface
texture for walls of cube (underwater)
Texture used for four walls (underwater scene)
texture for sandy ocean floor
Texture used for ocean floor

The background ocean scene is made using the skybox code from the WebGL water demo. It uses a custom shader to soften the shadows at the edges of the CubeGeometry to create an illusion of continuity. This would also require textures that wrap seamlessly between the faces, but we did our best with the textures we found.

Lighting

scene with default white lighting
Scene with default white lighting
scene with altered blue-green lighting
Scene with altered blue-green lighting
scene with transparent crepuscular ray texture over camera
Scene with transparent crepuscular ray texture over camera

To achieve an underwater effect, we used a blue-green ambientLight and a yellow spotLight shining from above the scene to mimic the sun. We also attached a semi-transparent water texture to the front of the camera to emphasize the effect of underwater crepuscular rays.

Camera

We restricted the OrbitControls of the camera so that the user wouldn't be able to zoom out of the scene and break the illusion.

Animation

The page listens for key presses from the WASD and IK keys to animate the submarine by changing the direction vector used to calculate its movement. The A and D keys rotate the submarine to the left and right respectively, and updates the X property based on sin(rotation) and the Z based on cos(rotation). The submarine is restricted from leaving the scene as the code checks its position.
The manta rays are animated to swim forward, and loop back to the other when they reach a certain point outside of the scene. The rays have slightly different randomly-generated speeds to give some variety to how the scene looks.

Future Plans

If we'd had more time, we would've liked to animate the manta rays' wings to flap realistically as they move through the "water." Doing this would involve calculating a function to animate the Bezier surfaces' control points, which would move roughly in the shape of a sine curve.
It also would have been nice to create a more realistic-looking background that hid the fact that the scene was contained in a box, and add some decoration to the ocean floor.
We also wanted to implement Three.js's animated water shader for the surface of the ocean, but instead used a static water texture due to time constraints.
We were also thinking of adding a second camera view from the perspective of the submarine, as if the user was sitting in it.