[Solved] Water Depth Map Precision Problem

Ok so what I’m trying to do is use deferred rendering to draw my terrain and other geometry into my world then use forward rendering to blend water (a quad with a water shader) into the terrain.

This kinda works except it has an ugly edge jagged edge where the water quad intersects with the terrain.

Ok so I thought i’d use the approach of “Soft Particles” to reduce the alpha of the pixel the closer it is to the terrain. Which looks great… sort of.

If you move far enough away your water vanishes completely (since I think the depth stored in my depth render target becomes almost the same as the depth i’m writing). Same thing happens if you move the camera directly above it… I’m thinking for the same reason (Assuming the water quad is pretty close to the terrain).

This led me down the path of linear depth buffers (since I currently write the depth with z/w which is the default way but also leads to almost all your precision being close to the near plane from what I’v read.

I found the formula to create linear depth somewhere on gamedev:

(Position.z * Position.w - near) / (far - near)

So in the vertex shader I put z and w in an output paramter (Depth) and in the pixel shader I do

float depth= (PSIn.Depth.x * PSIn.Depth.y - near) / (far - near);

Make sense? Hopefully that should be my terrain writing out a linear depth buffer to a render target. Drawing the depth render target with a spritebatch looks fairly sensible.

So all I should have to do now in my water shader (forward rederring so I can use transparency since it’s water) is the exact same thing as the terrain shader for creating the depth but in the pixel shader compare the depth of the pixel being drawn to the pixel stored in the depth map?

Is this correct? I’m not sure why it’s not working properly. I turned off the “soft” aspect of it for not and just did a compare/discard to keep things simple like I was before with the z/w depth buffer but I’m getting some weird results when I rotate the camera and as I move around it seems like i’m chasing the edge of the water. And the added bonus of the edges looking jagged from a long way away now (rather than invisible which was almost preferable). I’m currently stumped.

Anyone have any ideas what I could be doing wrong?

I think @kosmonautgames did some great stuff with this kind of thing but I’m not sure he’s still around.

A few things to think about.

  • Linear depth
    Normally you would just write the Z value of the world position from your vertex shader, but their is a problem with that. What you really want is the world space DISTANCE from the camera rather than the Z coordinate

  • Custom depth buffer
    There are other options than using logarithmic depth or linear depth. You can define your own depth equation that puts the precision in the range you want. Look at this for a decent discussion of what can be done
    https://outerra.blogspot.com/2012/11/maximizing-depth-buffer-range-and.html
    http://dev.theomader.com/depth-precision/

1 Like

Thanks Stainless. I shall have a look at those.

I actually ended up not having to change the depth buffer at all.

I different method of blending the terrain into the water did the trick. Calculating the water depth to determine the opacity.

Described here: (ok its java and Open GL but the principles are the same)

It has some other nice little tricks in there too for some more realism that are easily used in MG too.

1 Like