Water fading out near the shoreline?

Started by
7 comments, last by mictian 18 years, 7 months ago
Hello. I'm doing a little game where I need to render some simple heightmaps with a little lake or something like that once and a while. The look of the water I want is that it should be in a plain blue color, but near the shoreline it should fade nicely to transparent so it would give the appearance of shallow water. I also want small waves going towards the shorelines. But I have great problems achieving this effect and I've made several approaches so far that haven't worked out at all. My last and simpliest approach so far only involved to try to fade the water near the edges. I just made the waterplane like a flat heightfield with colorable points and then colored the points belonging to the quads in the heightmap that intersected the waterplane. Looks horrible.... And another problem I get while doing this is that depth test isn't working good at all for the waterplane <-> heightmap. Why is that? See this screenshot: http://henell.com/daniel/water.jpg I really need guidance to achieve nice looking water! :)
Advertisement
You may do like this:

1) render scene depth-info (not including water!!!) w/o any textures and so on, only naked triangles, without blending or alpha test. This is done in twice-speed on modern hardware. After, save this Z-info into a texture (via glCopyTexSubImage2D or via FBO, however you want to)

2) render your whole scene without water

3) render water, and in pixel shader get the difference between renderable fragment and that, stored in depth texture. Note, that it is not linear! After, modulate your water fragment transparency due to that difference (by formula in PS, or by look-up in 1D texture, no matter)
A less elegant but easy solution is to use simple per vertex alpha blending.

First draw the terrain as usual. Then set the render state so that the source fragment is weighted by its alpha value, and the destination fragment by one minus the alpha value. Then tesselate the water so that the triangle density of the mesh is not too sparse around the shore (or you could just draw a mesh of quads). When specifying the colour of each vertex, calculate the difference in height between the ground and the water, and use this (maybe after scaling it) as your alpha value. This could be pre calculated.

This method isn't as accurate as Jackis', but it still looks good and it's easier to set up and code.
MumbleFuzz
One more solution!

For every water patch (whole closed water area) you might compute transparency texture on preprocessing. I mean, you enclose all this water patch by rectangle, and linearly map this rectangle to texture. After, for each texel of texture map, you map it to corresponding water point, evaluating it's transparency, as heightfield difference function, and store it in a texture.

This method negliges you to subdivide all your water areas to rectangles (as mentioned above), and render them with transparency function as simple texture look up! This is more accurate, that MumbleFuzz's method, cause it's not per-vertex based (MumbleFuzz's method is highly depends on water tesselation).

I think, that for your planar water with such a landscape geometry, as in screenshot, is the best solution, because my first method requires ps2.0 (or arb_fp1 in GL) pixel shader version (GeForceFX+ or Radeon9500+ hardware required).

Good luck! If any questions - I appreciate to help you!
You're in dire need of a fresnel term, for one thing. Compute the dot product of the water's normal and the water->camera vector; when it's 1, render transparent, and when it's 0, render opaque. Interpolate between the two accordingly.

When you render the heightmap originally, you could also fade vertices to black/blue as they go down beneath the surface of the water, simulating the fogging effect you get underwater.

As far as how to implement that goes, use shaders.

Don't make the water part of the heightmap - you need that section of the heightmap to represent the geometry beneath the surface of the water.

Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse

Actually I have already solved my problem with a solution almost the same as the second one Jackis suggested! I did it with a texture, a texture animation even and got some nice waves going towards the shore :) Looks very neat for have been done by me, usally my stuff don't look this good :D
http://henell.com/daniel/water2.jpg

What do you think? Please give me all suggestions you have for makeing it look better! :) As for shaders, I have never used them and I have barely any knowledge about it. Where can I read up about it?

Thanks!
looks nice

if you are interested in simulating more optical properties of water then you should add some hints towards refraction and reflection, as these are good visual clues to the nature of the surface.

the usual cheesy kludge way to do this is to render the _inverted_ world to a texture, render the refracted world to a second texture, and use a shader to weight between these textures (which are projected back into the scene)

the weighting uses the "fresnel term" which you can google.

i have a small demo + source of these effects at
http://people.umass.edu/rwhall
if you are interested I will help you understand the code, but what you should know is that this trick is not physically accurate, just a cheap way of parameterizing an effect that has too many variables to do properly...
¿We Create World?
forgot to mention that demo bugs out on nvidia hardware...i will fix it shortly
¿We Create World?

This topic is closed to new replies.

Advertisement