PDA

View Full Version : stencil buffer question



m4ch0dude
04-26-2004, 09:03 PM
I'm working on a terrain engine that draws reflections in the water. Basically it draws the world upside-down, clip using stencil buffer to only show in the water, and blend with the normal world. The problem is that the terrain that's under water (not the upside-down world) gets blended with itself when viewed at low angles, and I'm not sure how to fix it. Here's my basic rendering code:

if(camera above water){
//setup stencil buffer and draw water into it
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
glDepthMask(GL_FALSE);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
DrawWater();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glPushMatrix();
//draw upside-down world
//setup clip plane to water level
...
glScalef(1.0, -1.0, 1.0);
DrawTerrain();
glPopMatrix();

//draw underwater terrain
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
DrawTerrain();
...
glDisable(GL_STENCIL_TEST);

//draw water surface
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
DrawWater();
glDisable(GL_BLEND);
}
//draw regular world
DrawTerrain();

If anyone can help me, I would appreciate it

Relic
04-27-2004, 12:58 AM
You already have the solution in the comments:

//setup clip plane to water level

Just do it.
If it was glClipPlane(GL_CLIP_PLANE0, {0.0, 1.0, 0.0, 0.0}) before, set it to GL_CLIP_PLANE0, {0.0, -1.0, 0.0, 0.0}) or do it after the glScale because the clip plane is transformed by the inverse modelview matrix.

While scaling with (1.0 -1.0, 1.0) you need to reverse the glFrontFace, too.

Edit: Ok, scratch the first part, you seem to got that right. If it's just blending in the underwater terrain against itself, this may need front to back sorting and depth comparison enabled, or you need to rearrange the ordering in which you draw the scene. Draw the underwater terrain first and don't blend it.
If you don't use refraction tricks, it's not necessary to draw the over- and underwater terrain in two steps. Drawing the reflection inside the stencil buffer is the only special treatment.

m4ch0dude
04-28-2004, 07:38 AM
Yeah, the clip plane works fine. The reason I made the underwater terrain seprate is because I want to render the upside-down reflections and still be able to see the ocean floor, and since the reflected world is underneath the ocean floor, I had to enable blending. I think I might have to change the stencil op used on the underwater terrain, maybe that would fix it. Anyways, thaks for your advice.

jeickmann
04-28-2004, 08:15 AM
If you want to avoid the blending of the underwater-geometry with itself, you could try to render the mirrored geometry to a texture without blending and then apply that texture to the water-surface using blending.
There's an old SIGGRAPH course on planar reflections with render-to-texture, I think.
This way, you can also do some pertubation of the texture-coordinates in order to simulate little waves on the surface.

Take a look at ATI's nature-demo. They do something like this and you can even enable it to show you the rendered textures in a little window.

Jan