Reflection of big surfaces like water (GLSL)

Started by
6 comments, last by theprogrammer12 13 years, 5 months ago
I made a program that renders a cube map from the center of a sphere to make reflection and it works fine, but this won't work with bigger, flat objects like water as the cube map is rendered from the center only. Should I render many cube maps or is there another way?
Vista sucks
Advertisement
You can use planar reflection. Instead of rendering a cube, you render the scene as normal, but with the camera flipped upside down beneath the water.

To get this 'upside-down camera', you can construct a reflection matrix from the water plane and multiply that with the view matrix. You'll also want to enable a user clipping-plane so that objects below the water's surface don't show up in the reflection.

Once you've rendered that to a texture, you can use the reflected view-proj matrix to project this texture onto the water (during your main pass).
Planar reflection only seems appropriate for a perfectly flat water surface though. If you had any ripples or waves in the water this would send your normals scattering out in all directions, thus the need for the cubemap (I don't know if this is OP's case though).

In that case, I guess you would just have to live with the distortion, or make a cubemap that is large relative to the object so that the inconsistency is unnoticeable?
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game
you could render the geometry that is visible to the water
using a paraboloid mirror into a single texture

but what will the fresnel term be for the water surface reflecting geometry behind the camera?

mostly approaching 1.0 = refraction only

which is why you can get away with simple reflection map

no need to mess with cameras for reflection maps:

vs: posWorld.y *= -1; // reflect geometryps: clip(-posWorld.y); // clip anything above waterrs: cullmode = opposite of usual // flipping y reverses triangle winding


refraction map even simpler:

vs: no changeps: clip(posWorld.y);


when the camera goes underwater you just need to flip the clipping

(underWater is -1 or 1)

clip(posWorld.y * underWater);


now to sample the reflection and refraction maps you just need

vs:static const float4x4 matTexProj = float4x4(	0.5, 0.0, 0.0, 0.0,	0.0,-0.5, 0.0, 0.0,	0.0, 0.0, 1.0, 0.0,	0.5, 0.5, 0.0, 1.0);//float4x4texProj = mul(posProj, matTexProj);ps:color = tex2Dproj(smpReflect, texProj);


(doing it this way means you avoid the slow dependent texture read)

[Edited by - skytiger on November 11, 2010 7:00:55 PM]
Quote:Original post by karwosts
Planar reflection only seems appropriate for a perfectly flat water surface though. If you had any ripples or waves in the water this would send your normals scattering out in all directions, thus the need for the cubemap
It's technically not correct, but you can use the normals to offset the UVs when sampling the planar reflection texture. It will still look much better than a cube-map.

Quote:Original post by skytiger
no need to mess with cameras for reflection maps:
*** Source Snippet Removed ***
Assuming your reflection plane is horizontal and passes through the origin ;)

Also, instead of changing the cullmode to be the opposite of usual, you can isntead scale by -1 in the x axis (and flip your UVs horizontally when projecting the texture to undo the scaling). I find this easier than having to manage inverted cull modes for everything.
Quote:Original post by skytiger
no need to mess with cameras for reflection maps:
*** Source Snippet Removed ***


thinking about it some more, my y *=-1 technique has some small issues:

a) it is easier to feed an existing shader an adjusted view matrix
b) any view-dependent lighting/reflections on the reflected geometry will be wrong (think specular or rendering a mirror reflected in water)

which means a reflection isn't always a mirror image ... lol
A reflection using render-targets is unnatural, that is why it is/seems wrong. You would have to use planar reflection for every triangle and that is overkill (even with gpu horsepower and very fast stencil buffer);
Although this is very noneffective and thus impossible on current hardware. You can though approximate a water surface with plane and objects with cube or sphere around if (e.g. cube map, respectively sphere map).

If you want a robust solution for reflection that is correct, you probably would have to use ray tracing (and probably pretty much complex solutions to achieve correct water surface).

My current blog on programming, linux and stuff - http://gameprogrammerdiary.blogspot.com

Thanks everybody! I'll try to do a planar reflection and change the coordinates using the normal vectors from a normal map...
Vista sucks

This topic is closed to new replies.

Advertisement