Home » Community » Forums » OpenGL » Reflective surfaces (e.g. water)
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic

Page:   1 2 »»

 Last Thread Next Thread 
 Reflective surfaces (e.g. water)
Post New Topic  Post Reply 
I'm trying to create a reflective surface just like mirror or water. I've read a lot of posts on this topic and I think I've got the theory by now:

1) You flip the geometry around the water plane
2) You set the water plane as a clipping plane (so that things under water aren't drawn)
3) You render the scene to a texture

But as easy as that sounds I've still some questions:


- What's the easyest way to flip my whole geometry (that are a LOT of objects) about the water plane? Is there some easy trick like moving the camera/changing it's up vector??

- How do I define my own clipping planes?

- How do I apply that texture to my plane? What texture coords should I use and where do I get them????



Lots of questions...but hopefully lots of answers, too....

Thanks a lot, FunKurt

 User Rating: 1022   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

>- What's the easyest way to flip my whole geometry (that are a
>LOT of objects) about the water plane? Is there some easy trick
>like moving the camera/changing it's up vector??

Use glScale-functions.
glScalef(1, -1, 1); // Flips y

>>How do I define my own clipping planes?
Use glClipPlane(GL_CLIP_PLANE0, plane_equation) to define the plane.
Then use glEnable(GL_CLIP_PLANE0) to enable it.


 User Rating: 1023   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I'm looking into this, too, and I was wondering if you should define a sort of viewing box coming out from the water so you only draw reflected objects that have reflections you can see from your current position. Is this right?

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Thanks circuit!

But what about the texturing? How does that work?
I think it would be difficult to map a texture on a quad which has been rendered that way...

 User Rating: 1022   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I've tryed google in order to find some tuts/samples, but it's all about stencil reflection, which not what I need...

Maybe smeone has got a good link???
Thanks!!!

 User Rating: 1022   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I think there is another way using the stencil buffer.
It goes somthing like:
draw your reflective surface into the stencil buffer,
flip your geometry and redraw it to the colour buffer only where the stencil buffer is set.

---
When I'm in command, every mission's a suicide mission!

 User Rating: 1033   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Is this method suitable for large planes? (I mean REALLY big, so that the player sees only a very small part of it at a time)

 User Rating: 1022   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Yes. The stencil buffer is just as big as the color buffer (your screen). The only limit that you have is that ou have to render your terrain twice. Once flipped over Y and once normal, so it takes longer.

I hope you have a good frustum culling / occlusion culling method!

Sander Maréchal
[Lone Wolves Game Development][RoboBlast][Articles][GD Emporium][Webdesign][E-mail]


GSACP: GameDev Society Against Crap Posting
To join: Put these lines in your signature and don't post crap!

 User Rating: 1817   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Allright then! Thanks for your support.. I'll try that as soon as possible :-)

 User Rating: 1022   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Hi there!

The glScalef(1,1,-1) works great... except for one thing.

The models get all funky normals... if I flip a box, it´s like you press down the top of it and through to the other side... thus, leaving the box inside out. <- not nice! =)

Is there a function for flipping the normals? thanx!



P.S would it be better to have several small quads of water(textures), or just one quad/trianglepair with one texture wrapped all over it? I recon the one quad solution is pretty fillrate punishing..?

"Game Maker For Life, probably never professional thou." =)

 User Rating: 1064   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Seems like glRotate wouldnt have that prob. Im not sure tho

 User Rating: 1075   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Sorry, but it's me again ];-}

I've got a problem with this stencil-thing:
The reflection is created through a second render pass, but this way you cannot use any pixel shaders, right? Is there a way to use stencil reflections to generate a texture, which is then applied to my water quads?

 User Rating: 1022   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Why wouldn't you be able to use pixel shaders? Are you sure you understand how to do stencil reflections?

1) turn off all pixel shaders, textures, light etcetera
2) render waterplane to stencil buffer
3) enable stuff from (1)
4) flip geometry over the water plane
5) enable clipplane over the waterplane
6) render geometry with testcil test (only render where stencil buffer is set to 1 in step (2))
7) undo (4) and (5)
8) render waterplane (blended)
9) render geometry again

Sander Maréchal
[Lone Wolves Game Development][RoboBlast][Articles][GD Emporium][Webdesign][E-mail]


GSACP: GameDev Society Against Crap Posting
To join: Put these lines in your signature and don't post crap!

 User Rating: 1817   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Dont use the scale -1 because it makes the normals crazy as you described, the rotate is not right either, since you need mirroring, not rotation (the scale is right in theory)

I think the best way is to tweak the camera. Can't remember the details, but I once made a rippling reflective water for a small game. You can download hte sources here:

http://moppi.inside.org/eskimo/

The stuff you are interested of is in the SceneC.cpp

 User Rating: 1023   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Excuse my stupidity.. ;-)

In step 8, do you use the texture you generated in step 6?

 User Rating: 1022   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

No, you don't generate or render any textures. You are simply drawing, and redrawing parts of you scene and blending them all together for the final effect.

Read Sander's instructions again, they do make sense. But here is another description.

Say you have a pond, you want to render a reflection but don't want the reflection to appear on the ground next to the pond. You disable colour and depth buffers, and enable the stencil buffer.
Now, you draw *ONLY* your pond surface. This will set an area in the stencil buffer, like a little cutout.
Now if you render into the colour buffer, you will only see objects that appear where the stencil buffer is set, so, you flip your objects about the reflective plane, and draw them. Now you should have objects in that little cutout area and they will be flipped over and look like a perfect reflection.
Now all you need to do is draw your pond surface again, with blending and it should now look like water with a reflection on it.
You don't need to use any textures you have generated from prvious steps.

---
When I'm in command, every mission's a suicide mission!

 User Rating: 1033   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Hey there. The reason why your objects will be inverted is that the scale(1,-1,1) reverses the winding order of your vertices.

In OpenGL you can correct this by doing something like the following

// render the actual object
glFrontFace(GL_CCW);
RenderObject();

// render the reflection.
glScale(1,-1,1);
glFrontFace(GL_CW);
RenderObject();


As a side note, you can perform frustum culling by perform the exact same transformation (in this case glScale(1,-1,1)) on your bounding box/sphere/volume, and then testing it against your frustum.




 User Rating: 1216   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Allright, I got that! Thanks!

The big BUT:
I would like to apply a UV-distortion pixelshader to the water-texture to make it look better. (Using a normal map to do bumpmapping and to perturb the UVs of the reflection texture)

But for that I'd need a texture. So stenceling is not suitable here...(or at least I think so), right?


Thanks for your support!!!

 User Rating: 1022   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I see, what your problem is :D

You are simply trying to copy the reflection down to pixel, so you can disort it with the pixel shader / fragment program ?

There are different ways to get that work (I think)...

You can create a new viewport. Render the water texture in it, and render what you have in the stencil to it afterwards. And last copy the viewport to a texture and then disort it. I don't recommend it because this way can be extremly slow if you arn't good at optimizing.

Otherwise you can render the thing from the above (water and stencil) to the texture directly with the pbuffer extension (it is an ARB extension). Read about it. It's much faster but a bit more complicated than the above solution...

Hope you can use some of it :D





[edited by - olekaiwalker on August 23, 2003 11:17:26 AM]

 User Rating: 1013   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

@ OleKaiwalker:
Just in case you are bored... could you explain that a little more in detail? For example: If youe render a texture that way, how can that be mapped onto the water plane?

"Otherwise you can render the thing from the above (water and stencil) to the texture directly with the pbuffer extension (it is an ARB extension). Read about it. It's much faster but a bit more complicated than the above solution...
"


THAAANKS!!!

 User Rating: 1022   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Ok here it goes

With solution 1, you will have to create a new viewport at the size of the texture (not above 512 x 512, it will slow down it all) and then you render the texture (water) in the new viewport and use stenciltest to get the reflection. Next you use glCopyTexImage2D() to copy the viewport's data to a bound texture, and the texture can be used as any other texture :D

With solution 2, you'll have to do the same as above, but this time you don't have to create a new viewport and don't have to copy something to the texture (much faster). You'll have to create a pbuffer (through extensions) and then you'll just choose it and render to it, and afterwards you will choose the normal buffer again and use the pbuffer as a texture, which can be mapped onto the waterplane.

Think of it as doing your calls (glVertex3f and such) on a texture instead of on the screen.

 User Rating: 1013   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Yezzz, double-smile-uber-grin! I think I've got it now...
Thanks a lot, man!

 User Rating: 1022   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Ha, zu früh gefreut... ARGH!


Here you can see the waterplane and reflection (of two islands) rendered:



But if I apply this image as a texture to the water quad again, that would look definately NOT right ;-)

So, is there something wrong with your explainations or my head *g* ??

 User Rating: 1022   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:

So, is there something wrong with your explainations or my head *g* ??


Neither

There is just one little detail that you and the explanations missed: projective texturing. You can't just apply the texture as a planar map onto the water surface, that would obviously not look right: the perspective projection would be applied twice. Once when rendering the reflection texture, and once again, when rendering the texture on the water surface. That's not what you want.

The water reflection texture already encodes a projection in the texture image. Thus, you need a special, perspective aware method to texture your water surface with this pre-encoded map. And this method is called "projective texture mapping". Think of it as a slide projector, that projects your rendered reflection image onto the water surface, from the point of view of the camera. Check out this nVidia paper for an introduction.


 User Rating: 1996   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Hum, yeah. That makes sense ;-)
Thanks!!

 User Rating: 1022   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link
Page:   1 2 »»
All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: