I’m creating a terrain engine, and I got the terrain working good, but now its time to add water.
I want to achive something like in CoD, or Halo, or Joint Operations.
In Joint Operations it renders a ton of water, and I have no idea how they can calulate all of those normals!
How should I come about rendering large bodies of water realy fast?
One thing to remember is to use GL_ARB_vertex_buffer_object. You’ll see some major improvements in speed using that extension. Also to get really good looking water you should probably use a FFT (Fast Fourier Transform). You can probably do all that math on the GPU now. Something I have been planning on looking into for one of my future demos. So if you have GPU cycles to spare it would be a good thing to make it do the FFT. There is a really good article on gamasutra.com that describes realistic deep water (ocean) rendering. Be sure and look for that. There are various water demos by nvidia that you will see included in their latest tools like the FX Composer, Cg browser, etc.
BTW, there is a link to a demo that implements the gamasutra ocean rendering article. It looks very good and runs pretty fast. http://meshuggah.4fo.de/
Here is another link to a water rendering demo that includes source. There is also a paper about it. http://claes.galaxen.net/ex/
I hope those are usefull somehow.
The last time I was swimming I took some time to relax, sat down on the edge of the pool and took a look at the water and tried to find out what it’s really about, what makes the visual effect you see when you look at water.
Basically it is a mixture of a reflection of the environment on the water surface and the things things below the water surface. And of course, the water has got waves.
This makes four important things when rendering water, at least that’s my conclusion and the way I implemented it:
the water plane itself is rendered simply as a plane, made up of triangles, and the waves come from bump maps, or rather one bump map that gets tiled across the plane (might look nasty due to the tiles, but there are some tricks to minimize this effect)
the reflection on the water. you have to render the scene upside-down, mirrored along the waterplane, capture this to a texture, which you can use for the mirror image, mapped orthogonally on the screen. the texture coordinates are disturbed/perturbed FOR EACH FRAGMENT by a fragment program, and for this distortion, the normals from the water plane bump map is used as an offset (which is a very simple, unrealistic solution)
the stuff below the water surface also is rendered and captured as texture image, and also gets orthogonally mapped on the screen, with tex coords disturbed fragment-wise according to the “wave” normals
the ratio of visibility of “under water stuff” vs “reflection” is depending on the angle between the viewing vector to the surface, when you look orthogonally down on the water surface, you almost only see the things under the water surface (which is, in ocean water, not very much at all = almost black), and the flatter your viewing angle ist, the more you see things reflecting on it. this means that you have to compute a blending value between reflection and “under water stuff” depending on the angle between the viewing vector and the surface normal, and as the surface normal comes from a bump map, you have to do this fragment-wise, also.
I hope this is not too much stuff, I felt a little bit like writing a tutorial about rendering water, but a) this is the way I do it in my app and b) I am a little drunk at the moment, so please forgive me . But basically, I think this is the way to do it on actual hardware.
Your points you made on rendering water seem to be fine, but if you want your waves to be some more convex, you’ll need to animate both: trangle mesh and bump map. Otherwise, even using the finest bump mapping technics it will always get flattened as you look at it closer or at sharper angles.
This is what ATI in its Chimp demo does and what some games do too, not just animating bump maps - you can see this especially good on the borders of water and some land.
Btw. If you stay with just bump map animation, maybe Parallax Mapping would produce better effects. It’s a good method for smoothly changing heights and has the ability to modify depth values, so might look quite good.
I am afraid that for a rather large amount of water, you need to have a rather fine mesh, which could slow down performance a little bit. But the main problem I got at the moment is how to get good animated water bump maps at all… if anyone has some he/she could send me, I would be very happy :-). The mesh animation also is not trivial, I guess. quite a lot of work to get good looking water, it seems. The water in the “mother nature” part of 3DMark03 impressed me very much… this is what water should look like. So if you don’t know this, download and see yourself, everyone.