Underwater environments look quite different from above-water environments.
Think about swimming underwater in a swimming pool. Light hitting the rippling
surface of the water creates focusing effects or "caustics" on underwater
surfaces (such as the walls of a pool). This interplay of light underwater
is an important cue for distinguishing underwater environments from above-water
environments.
Think about a 3D point-of-view game where the player can descend into watery
areas. Wouldn't it be great to add caustic effects to underwater surfaces?
It turns out such effects are straightforward to generate using a second
blended rendering pass in conjunction with OpenGL's texture coordinate generation
functionality and some caustic texture patterns developed by Jos Stam. Here's an example of underwater caustics (ie, rippling effects) simulated
with OpenGL rendering:
What you miss in the static pictures above is that the caustic patterns
are actually dynamic so that every frame you see a slight shifting of the
caustic pattern. You'll need to run the program on an OpenGL implementation
with good texture mapping and blending support to get the real jist of the
demo. An SGI O2 works great.
Jos Stam has several web pages with his various research results dealing with periodic
caustic maps. Check out Periodic Caustic Maps, Random Caustics: Wave Theory and Natural Textures Revisited, a SIGGRAPH '96 technical sketch by the same name, and Aperiodic Texture Mapping. What Jos Stam has done is created a technique for generating caustic-looking
textures that are both repeated spatially and temporally.
The rendering technique demonstrated on this page was first shown to me
by Angus Dorbie. The credit for
developing this rendering technique completely belongs
to Jos Stam and Angus.
Here are some more snaphosts. In this next snasphot, note that the caustics
appear on a cube just as well as they appeared on the sphere in the above
snapshots. The color of the light has been switched to a pure white light
instead of the greenish (watery) light in the above image. Note how the
light color interacts with the caustics.

In the snapshot below, a positional light (instead of a directional light
is used). Also note that the caustic ripples have been increased in size
(simply by scaling the texture coordinate generation plane equations):

The two snapshots below show how the caustics interact with a crude dinosaur
model. The image on the left has the caustics enabled. The image on the
right is missing the second rendering pass to add the caustic ripples. This
should help you see the contribution of the second pass:
Again, the contribution of the caustics is much clearer when animating.
The source code for the program pictured above is three C files and two
header files: underwater.c,
texload.c,
dino.c,
texload.h, and
dino.h. The thirty-two 256x256 8-bit
caustic texture image files used by underwater are contained
in the following zip file: caustics.zip.
You will also need floor.rgb.
As mentioned earlier, the technique involves a second rendering pass over
all objects in scene. The blend function used is:
glEnable(GL_BLEND);
glBlendFunc(GL_ZERO, GL_SRC_COLOR);
The important step is enabling texture coordinate generation with glTexGen:
GLfloat sPlane[4] = { 0.05, 0.03, 0.0, 0.0 };
GLfloat tPlane[4] = { 0.0, 0.03, 0.05, 0.0 };
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGenfv(GL_S, GL_OBJECT_PLANE, sPlane);
glTexGenfv(GL_T, GL_OBJECT_PLANE, tPlane);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_2D);
The texture generation will map the currently bound caustic texture object
onto every object in the scene based on its object coordinates. See the underwater.c source code for more details.
As the briefest aside, I'd like to point out that many other 3D APIs (Direct3D
in particular though) lack the texture coordinate generation capability
(present in OpenGL since release 1.0) that makes possible the object-coordinate
texturing of the caustic patterns onto arbitary geometry.
- OPENGL Web site