View Full Version : Length of ray under/above water

08-11-2014, 08:20 AM
Hi there,

In my project I started out with transforming positions and normals into world-coordinates, but I was recently suggested to just use eye-space instead. Now I run into the following difficulty:

In the world, everything under z=0 is underwater. In the case that a fragment is underwater, and the camera is above water, I apply the underwater effect, then then semi-transparant surface of the water, and than the fog effect for above water (the surface of the water is drawn in a separate buffer and I use deferred rendering for this)

To do this I need to know which part of the ray (from camera/eye to the fragment) is underwater and which part is above water (see picture). In world space I could solve this easily with my high school math, but in eye-space this seems more difficult.

I know you can find the intersection of a line and a plane with solving equations, but i don't know the equation for the plane (z=0 in world-space) in eye space, and I'm not sure if this is best way to go anyway. Basically I would like to know which part of the ray is underwater, and which part is above water... (not only the lengths, but I would like to know for both the fragment and the camera coordinates if they are underwater or not)

Can anyone advise me on this? thanks!

Dark Photon
08-12-2014, 02:28 PM
Sounds like you have a plane equation in world-space (Ax+By+Cz+D = 0), and you need it in eye-space. Well (A,B,C) is the plane normal in world space, which we can transform from world-to-eye space pretty easily, giving you (A',B',C'). Then take a point on the plane in world, transform it to eye, plug into A'x+B'y+C'z+D'=0 to get D'. That should be your plane equation in eye-space. Then can you do your ray-plane intersect and other ops on that?

I may be missing something in your question though.

08-31-2014, 12:06 AM
Personally I find thinking about planes as a point&normal vector representation much easier than plane equations. Transform both (normalmat*normal, modelview*vec4(point,1)) into eye space and the rest of the maths is the same: intersect = raystart + raydir * (dot(point - raystart, normal) / dot(raydir, normal))

On a related note, if you just need the distance through something (e.g. for absorption effects) a cool trick is to use blending and render the object to a texture twice, the first time additively blending only back face distance and the second subtracting front face distance. One limitation is the object needs to be watertight, or at least bounded by backfaces. In the case of water, the floor needs to be included as backfaces. For a flat surface, the plane intersection will of course be way faster.