Stencil Buffer

Hi guys, I’m trying to get a water tile in a simple tile editor to have a reflection on it using OpenGL’s stencil buffers. However I’m getting some weird behavior.

So I turn on stencil testing, render a small 1x1 tile, then render the clouds scaled(1,-1,1).

It’s reflecting the clouds I’m drawing, but it isn’t confined to within the 1x1 tile only. It looks like its showing all of the clouds, or at least a significant proportion of it.

Any help appreciated. Apologies for the code being in Java.

The whole clouds plane is 25x25.

Here’s a picture (the water like tile is the tile i placed down):


gl.glEnable(GL.GL_STENCIL_TEST);
gl.glColorMask(false, false, false, false);
gl.glDisable(GL.GL_DEPTH_TEST);
gl.glStencilFunc(GL.GL_ALWAYS, 1, 1);
gl.glStencilOp(GL.GL_REPLACE, GL.GL_REPLACE, GL.GL_REPLACE);
		
gl.glPushMatrix();
gl.glTranslatef(position.x, position.y, position.z);
gl.glBegin(GL.GL_QUADS);
gl.glVertex3f(0.0f, 0.01f, 1.0f);
gl.glVertex3f(-1.0f, 0.01f, 1.0f);
gl.glVertex3f(-(1.0f, 0.01f, 0.0f);
gl.glVertex3f(0.0f, 0.01f, 0.0f);
gl.glEnd();
gl.glPopMatrix();
		
gl.glColorMask(true, true, true, true);
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glStencilFunc(GL.GL_EQUAL, 1, 1);
gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP);
	
gl.glPushMatrix();
gl.glScalef(1.0f, -1.0f, 1.0f);
drawClouds(gl);
gl.glPopMatrix();
		
gl.glDisable(GL.GL_STENCIL_TEST);

// draw the tile again

Develop more, explain better. I didn’t really understood what you meant, and I’m sure this is the same for other people.

Do you clear you stencil between different tiles ?

Sorry guys, and thanks for the reply arts! I’ll try to explain it a bit better. I thought it might not have been clear, which is why i added an image. But i guess that wasn’t enough :wink:

Within the image, there’s 1 water tile which i placed down. On top of that tile, i would like it to have a reflection of the sky above.

The clouds you can see rendered onto the ground is the result of the code above:
gl.glScalef(1.0f, -1.0f, 1.0f);
drawClouds(gl);
Since you can see the clouds on the ground, it is reflecting the clouds above, but the stencil buffer doesn’t seem to just draw the part of the clouds that is within the water tile: ie. the QUAD drawn above.

The quad i’ve drawn within the code above is at the same location as the water tile is, which is drawn in the “//draw tile again” part of the code.

The stencil buffer is cleared every frame. I’m only drawing 1 water tile at the moment, so i shouldn’t need to clear buffer the stencil between tiles (no other part of the code uses stencils).

Please let me know if anything is unclear. It might be the case that I’ve misunderstood how stencil buffers work, but from the tutorials I’ve read, this seems to be what it can be used for.

Any input appreciated.

Regards.

Are you sure you enabled stencil test for you window ? Because your code looks good for what you want to do.

Thanks arts.

What do you mean by enabling the stencil test for the window? Is there somewhere else i need to enable something besides in the glEnable above?

Also, I’m not sure if this is an issue or not, since the tutorials don’t use their reflection in conjunction with anything else, but does it matter that i have other things rendered before the code above?

For example, the grass textured plane you see in the image is rendered before hand, as well as many other things.

Regards.

I don’t know about java and GL. But a quick search on google gave me that:

http://chrisingradschool.wordpress.com/2010/02/19/enabling-the-stencil-buffer-in-jogl-opengl-java/

For the second part of your post, it does not matter as long as you don’t enable/use stencil in the other parts of your code.

You learn something new every day!

Although i still have an issue with it, the stencil buffer is actually doing something now :wink:

There’s just so much less OpenGL code for java, so I’ve always been looking at c/c++ implementations only.

Thanks again arts.

You should consider rendering to an offscreen frame buffer object instead. By doing so you bypass all the problems associated with platform specific window management.

Hi BionicBytes, thanks for the reply, but would you be able to elaborate on that a bit more?

What do you mean by bypassing platform specific windows management?

By platform, are you referring to Windows/Linux/Mac, etc? Because since I’m coding in Java, that isn’t an issue. The stencil buffer problem was a difference in how Java in general handles OpenGL stencil buffers in the back end.

I may have misunderstood what you meant, so apologies if that is the case!

The stencil buffer problem was a difference in how Java in general handles OpenGL stencil buffers in the back end.

Exactly! All these things are platform dependant code (fudges to get OpenGL to work in that particular environment). All of that can be avoided if you perform all of your rendering using a FrameBuffer Object and just blit the scene back to the main buffer when finished with the frame. By utilising a FBO you avoid issues where you can’t allocate stencil, multi-sampling, etc,etc to the main window provided by the context creation process. The point is that FBOs use OpenGL cross-platform APIs to crete the buffer(s).

BionicBytes, this is just a flag to add at “window creation” :slight_smile:

Are you refering to stencil buffer attached to an FBO ?

Yes I’m referring to attaching either stencil render buffer or stencil texture attachment.
Most implementation combine depth and stencil together as either a single depth stencil buffer or texture.