View Full Version : Half Like 2 like water

02-19-2005, 09:52 AM
Hi everyone! Who knows, where I can find a good tutorial explaining how to do nice water effects in 3D? I googled many times, but everything I get is a lot of demos without any explanation.
They're nice. But everyting I get with them is a shader, wich is hard to understand.

02-19-2005, 11:21 AM
There are some water discussions on this web site by Yann: http://triplebuffer.devmaster.net/misc/yannl.php

The water effect is fairly simple to make. It does look cool though I think. A basic run down of probably what they do is move the water mesh vertices up and down in a vertex shader by some function that looks like water movement. Then the water surface is rendered with a reflective cubemap for environment reflections. Also refractions are calculated for the scenery under the water. They also use some type of fogging effect when you are under water based on the depth of the water I'd suppose. Oh yeah, the fresnel term is also calculated on the water surface.

The latest update of the Source SDK allows you to make your own shaders...so maybe they have the water shaders included for examples. I don't know as I havn't updated my HL 2 in weeks. It's worth a look.


02-20-2005, 08:32 AM
Hi glJack!

A water shader is relative easy to do. Here is a quick overview of one possible algorithm:

1. Render the scene scaled by(1.0,-1.0, 1.0) to a texture. Use glClipPlane to render only geometry above the water. This is your reflection texture.
2. Render scene to texture. Use glClipPlane to render only geometry under the water. This is your refraction texture.
3. Make du/dv normalmap which fits to the normal normalmap. (I think HL2 uses animated normalmaps)
4. In your fragment program, add the scaled du/dv map to the projected texture coordinates (which you use to project the reflection and refraction back onto the geometry).
5. Load the reflection and refraction with the new tex-coords. (TEX reflection, newtexcoords, ...)
6. Calculate fresnel term. You can approximate it with 1.0-dot(normal, viewpos).
7. Modulate reflection with the fresnel term and the refraction with the inverted fresnel dot(normal, viewpos).
8. Modulate refraction with water color.
9. Add refraction and reflection.
10. Calculate specular highlight and add to result of 9.

Foggy water
1. method:
for a foggy effect you need to render the depth to texture, calculate depth^x, x depends on how foggy you want the water to be (small x -> more fog). Invert the result.
Modulate refraction with the inverted fresnel term and then with inverted depth^x. Modulate depth^x with watercolor and then with inverted fresnel, add the result to refraction.

2. Method:
When rendering the refraction texture, enable fogging.

Of course there are other ways to simulate water. But this way gives nice results. Here is screen from a demo i'm currently doing: Water (http://www.bonzaisoftware.com/screens/swater.jpg)

happy coding,

02-21-2005, 03:21 AM
Honestly that's the best water effect i have seen so far. Are you planning to release a tutorial with source code one day ?

02-21-2005, 04:07 AM
I only planned to release the app with shaders and about the same description as in my last post, but maybe i write a tutorial if i find some time...

I'm satisfied with the result, but i think it would look much better with animated normalmaps (currently the normalmaps are just moving across the surface).


02-21-2005, 09:18 AM
Thaks for help guys!
By the moment I have read a lot of tutorials about water shaders, And now I am writing a water shader demo. Actually, water shader won't be the only one in demo. Well, I have already implemented rendering to refraction & reflection maps lighting of water surface, but haven't yet done rippling of reflection / refraction textures based on the normal map. Although everyone says It's not the hardest part in the water shader, I still do not understand well, how it's done.

I think that water in HL2 is the best done in game water ether. I don't know if it uses animated normalmaps, but what I do is mixing two normalmaps together (actualy 2 normal maps with one source and 2 different texcoords) It looks pretty good now, I think it will look even better when I add reflection and refraction maps.

>>Modulate reraction with the inverted fresnel

do you mean
reflection = 1 - dot(normal, view)
refraction = 1 / reflection ?

Thanks for help! glJack

02-21-2005, 09:22 AM
What a cool screenshot! Nice work! I hope my demo will look smth like this.
By the way, Why do game developers like to add barrels to game levels? ;)

02-21-2005, 10:54 AM
I think the Far Cry water looks the best, perhaps because it's reflecting really beautiful natural scenery.

02-21-2005, 12:07 PM
HL2 seems to do it's water using only a normal map. I think the water's geometry is a flat surface.
If you cause a splash, it doesn't effect the normal map.
The reflection and refraction also look like it's getting torn (It looks blocky). I have everything maxed up.
I have to take a look at this FarCray some day.

02-22-2005, 08:37 AM
Originally posted by glJack:
do you mean
reflection = 1 - dot(normal, view)
refraction = 1 / reflection ?
No, like this:
reflection = reflection * (1.0-dot(normal,view))
refraction = refraction * dot(normal, view);


02-22-2005, 10:48 AM
That's some slick looking water there FullAmmo. I just recently wrote water shaders myself for my own little project. I use this method:

for ARB_fragment_program HW:
fresnel = pow(1 - dot(normal, view), 5)

everything else:
x = 1 - dot(normal, view)
fresnel = x * x * x * x

And then use the fresnel term to lerp between my reflection and refraction colors.

Here's a screenshot (http://www.ignh.info/main.php?page=gallery&id=60)
There are a few more screenshots here (http://www.ignh.info) as well as a few videos of it in motion.

02-23-2005, 03:41 AM
Your water looks very good fenris, i like it.
I first also calculated the fresnel term like you, but i felt it was too transparent for foggy water.
The water was supposed to be slick, i made it for small areas of water without big waves.

02-23-2005, 03:21 PM
This is the right thing to do, if you want foggy or dirty watter then the contribution from the bottom should account for that, i.e. attenuate or 'muddy' the vector based on the distance from the ray to the bottom of the pond. This will get you realistic looking water of Far Cry quality. The only additional steps would be to refract the ray path for the bottom (using render to texture and dependent read) bonus points for applying caustic illumination to the bottom.

03-02-2005, 10:44 AM
Hi all you bright minds :)

I've implemented some reflection/refraction in my terrain-renderer, but I can't figure out how to avoid the artifacts near the "coastline"...

I'm simply rendering my reflections and refractions to a texture, then I interpolate some animated normals across my water-plane and dissort the texture-coordinates for my projected texture according to these... :)

I have a screenshot and a video available:

Screenshot (http://www.student.dtu.dk/~s021877/02563/water.jpg)

Movie (5.6 mb) (http://www.student.dtu.dk/~s021877/02563/refraction.mpg)

Best regards,

03-02-2005, 02:38 PM
Hi Roquqkie!

I had the same problem with my project. The way I solved it was to overlap the water plane by a bit when rendering my terrain geometry to the reflection and refraction maps. Just offset your clip plane little by little until it goes away.

03-03-2005, 08:50 AM
Originally posted by fenris:
Hi Roquqkie!

I had the same problem with my project. The way I solved it was to overlap the water plane by a bit when rendering my terrain geometry to the reflection and refraction maps. Just offset your clip plane little by little until it goes away.It's all about smoke and mirrors, hehe. :)

BTW, nice water shot roquqkie. It's funny how a simple water refract/reflect algo fascinates me so. ;)

Shiny things are good. :D