For our final project, we decided to create an ocean scene based off of the objects we created for a previous assignment: a submarine and manta ray.
You can view the demo here.
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.
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.
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.
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.
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.
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.
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.