Water in a terrain engine

I have a terrian engine set up, and i want to add water. I triwed to do this by simply having a semi transparent quad textured drawn at a certain height… This isnt bad except for the fact that there is REALLY bad jittering effect when the water meets the terrain. The waters edge jitters very badly there. does anyone know how to fix this.

a) increase the depth of your depth buffer if you can.

b) draw the water slightly higher, so it is further from terrain polygons that are roughly parallel to it.

c) increase the angle of the terrain polygons at the waters edge, so they are more perpendicular to the water (this goes with b)

d) use glPolygonOffset when you draw the water, might work…

for point a) :
Isn’t it rather decreasing the depth of zbuffer that would give a more precise zbuffer on the range covered ? Or did I missed something ? For me, the lesser zmax-zmin, the better the precision. Am I wrong ?

Originally posted by rixed:
for point a) :
Isn’t it rather decreasing the depth of zbuffer that would give a more precise zbuffer on the range covered ? Or did I missed something ? For me, the lesser zmax-zmin, the better the precision. Am I wrong ?

Correct, but ‘increasing the depth’ means increasing the number of available bits (via a different pixelformat) in this case I think.
And yes, mapping a smaller range of depth values to the available depth bits will also improve accuracy.

BTW: the difference between zmax and zmin is not the only important factor, it is also the ratio between zmax and zmin:
zmin = 100, zmax = 199 is creates better accuracy than zmin = 1, zmax = 100 even if the difference is 99 in both cases.




I usually set zmin=1, so I will fix it since its not relevant in many case if its 1 or 10 or even 100.

I didn’t know about this ratio thing. I will watch at the z calculations in the gl specs to understand why.


I’ve got the same problem and am using the same method as you are until I get a textured wavy surface going. When I zoomed my camera in and scaled my view down to keep everything the same size it helped enormously.

Try that and see what you think. Set your eyepoint closer to the scene, and render the scene smaller to keep it to scale. Instead of “zooming in” you’re just increasing the resolution so to speak.

I think.


just to clarify, yes, i did mean increase the bit depth of the depth buffer…

Thanks all, but i figured it out, there is a much simpler way of fixing this, just use multiple quads in a grid. Having just one huge quad covering the entire map was the thing stuffing it up… So now i have a bunch of smaller quads…

the Z-Buffer artifacts can be avoided in two ways:

  1. By increasing the zbuffer bit depth
  2. by setting the near plane a value bigger than 1, preferably set it 5 or 10 depending on how close do you want to look at the terrain
    if the value is too big , you’ll encounter some unwanted nearplane clipping…

good luck.

Mr. Shoe, more quads means a slower engine. You can fix your problem by using only a single quad and decreasing the ratio between the near and far clipping planes. For example:


will give much better results than:


Try it

More quads mean a slower engine, but how else can you get sinusoidal perturbations in wave height to emulate real ocean like waves?

I’ve got an additional “height map” for my ocean grid which I am using for just such a thing. The 3D texture mapped waves look really cool.

On another note, I noticed that when I switched my view to orthogonal (glOrtho) the visual artifacts between land and water disappeared entirely.


Just a few comments about my progress on the off chance anyone’s interested.

I load in a greyscale bitmap and generate my map information dynamically based on size (memory permitting). I’ve got an array set up for my terrain heights and an identical array for the water heights. The grid is fixed x/y, with z being up/down (traditional y). I texture every 8x8 cells with a 256x256 bitmap loaded from a list of textures used by the map.

First I display my terrain using GL_TRIANGLES, 2 per cell. I set texture coords accordingly to get the 1/8x1/8 slice of the 256x256 bitmap used for this 8x8 group of cells. Oh, I generate normal arrays on map load so I don’t calculate anything in run time.

Next I display my water also using GL_TRIANGLES, 2 per cell. Please note that I’m going to switch to STRIPS soon. Eventually maybe the vertex/normal array stuff, but that’s way down the road. For the water I use a water texture I loaded at runtime, tinted slightly blue. I calculate opacity for each cell based on water depth. The deeper the water the closer to an alpha of 1.0f. I clamp the alpha to some arbitrary minimum number that doesn’t result in invisible waterline (something like 0.25f looks OK). Finally I perturb the height of each cell based on a sine wave. I plan on perturbing the cell heights such that as the water depth decreases the sine wave is smaller and more frequent. I’ve wondered how to implement waves more realistically along the shoreline, since in real life you get the foam and crest and, well, white stuff where water meets land. Particles?

For somebody as inexperienced as I am it looks pretty darn nifty so far. Slow, but nifty. I’m on an old Slot 1 Celeron running at 454 Mhz with an 8 Mb Voodoo 2. Mu hah hah. We don’ need no stinkin’ Geeforce. Or rather, “… must … optimize … render loops …” Heh heh.

My main loop displays about 44x44 or 48x48 cells every frame. I don’t have a frame counter yet. My resolution is 1024x768 and 44x44 fills the screen with no artifacts on the edges when scrolling over any terrain height. Anyway, that’s about 9,200 tris per frame with the terrain & water maps. It scrolls about as fast as Warcraft II with 7 computer players with maxed number of units. Heh heh. Just kidding. It chops a bit on my PC. I am looking forward to the performance gain from strips. Anyway.

Finally I just started fiddling with code to add trees. Eventually it’ll include all non-terrain objects such as troopers, buildings, etc., but right now it just does trees. Or tries to, anyway. Haven’t put more than a couple of hours into that part, and plus, it’s off-topic.

I’ve no doubt rambled enough for now.

If anybody’s interested I can upload a demo to my website for review. I’d be interested in hearing what you think of the water effect. You can load any 24 bit greyscale (yeah, haven’t converted that part yet either) into it as long as you’ve got enough memory to handle it.


Hi Heaven,

I would like to see your terrain demo. I am wanting to start work on one myself but still too new at OpenGL to know where to start.