I’ve been wondering for a while how to make water look more like water in my game. If you’re thinking about transparency, well… you can get a simple transparency effect just by coloring underwater areas. If you really want/need to use the alpha channel instead, you probably have to sort your geometry back to front before rendering (see this link at opengl.org for an overview of what’s involved).
A simple principle can be used to render water using reflections – just render the scene all over again, mirrored against the XZ plane that defines your water…
// 3. translate back after mirroring.
glTranslatef(0.0f, water.level, 0.0f);
// 2. Mirror the scene. I add a little bit of animation with sin(period)
// for effect (see below)
glScalef(1.0f, -0.8f+sin(period)*0.08f, 1.0f);
// 1. move to water level before reflecting the scene.
glTranslatef(0.0f, -water.level, 0.0f);
// … (re-render your scene, or just a small part)
// that’s for animation, won’t make your water ripple, but without shaders…
// (no processing overhead)
3,2,1 goes in reverse order, that’s just how the GL transform chain works.
The next question is then, how do we color the water. I’ve been looking for a simple way to apply a color filter via the GL, but couldn’t find anything. Here’s a few options to consider:
- Colored GL lights. That’s probably the easiest. Reflect your light sources and change their RGB values. That’s also processing intensive. As if re-rendering significant chunks of your scene wasn’t enough…
- Global ambient. You can set the global component of a GL light. That’s what I’m using right now. I feel suspicious, however… this doesn’t seem to ‘just change the color’. The rendering looks like something more (processing intensive) is happening.
- Use vertex colors. likely, that’s among the fastest and flexible options. If your scene is static, you can just duplicate all your vertex color arrays and change each color component as you please. Sure, it’s a little memory intensive.
- Use material color, or better, just glColor. If you’re OK to render everything using the same color (just for your reflections), you can just disable your color arrays and pass a single color to the GL. Now that’s fast, requires no lighting and generates no memory overheads.