Sign in to follow this  
theprogrammer12

Reflection of big surfaces like water (GLSL)

Recommended Posts

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?

Share this post


Link to post
Share on other sites
Hodgman    51222
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).

Share this post


Link to post
Share on other sites
karwosts    840
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?

Share this post


Link to post
Share on other sites
skytiger    294
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 geometry
ps: clip(-posWorld.y); // clip anything above water
rs: cullmode = opposite of usual // flipping y reverses triangle winding



refraction map even simpler:

vs: no change
ps: 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
);//float4x4

texProj = 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]

Share this post


Link to post
Share on other sites
Hodgman    51222
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.

Share this post


Link to post
Share on other sites
skytiger    294
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

Share this post


Link to post
Share on other sites
Vilem Otte    2938
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).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this