hidden surface removal

I’ve having trouble implementing hidden surface removal. Here’s the setup. I draw two polygons. Let’s call them A and B. When I enable depth test (and clear the depth buffer), then A always gets drawn in front of B (even when I move the camera to behind B). When I disable depth test, B always gets drawn in front of A.

How do I make it so that the farthest polygon from the camera is the one that gets occluded? The tutorials I’ve looked at merely say to enable depth testing. But it seems there’s more to it than that.

Thanks.

Nothing more to do.

If you use glut, ensure to create your window with GLUT_DEPTH attribute.

Thanks art. But if there’s nothing more to do, then why would it always draw triangle A in front (even when it’s behind B)?

It’s evidence that enabling depth test does something since it makes A always in front instead of B. But then is there a way to make it so that A is only in front when it’s closer?

I’m not using glut. (Do I have to to solve this? If so, what command(s) do I use exactly?)

Arts is right, you need a buffer with the ZBuffer, enable depth test and set the depth function and clear the depth buffer at the beginning, also check glDepthMask this tell if the polygon are writing on the zBuffer

glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);
these are the default… but just to be sure.

BTW: here’s my code (which is in a step function):

  GL.Enable(GLFeature.DepthTest);

  GL.Clear(Buffer.COLOR_BUFFER_BIT);

  GL.Begin(DrawMode.Triangles);

  GL.Color(1, 0, 0, 1);

  GL.Vertex(0, 0, 10);
  GL.Vertex(100, 0, 10);
  GL.Vertex(100, 100, 10);

  GL.Color(0, 0, 1, 1);

  GL.Vertex(100, 100, 20);
  GL.Vertex(100, 0, 20);
  GL.Vertex(0, 0, 20);
  GL.End();

It draws two triangles–one red and the other blue. The red one is always the one on top (no matter where I position the camera). If I instead disable depth test, then the blue one is always on top.

If depth test is disabled, it’s normal that it’s always the blue triangle on top since you draw it after the red one.

I’m sure you have to ensure you create your window with depth buffer enabled (I don’t know how to do it for java or so), something like gl attributes for your window.

Not sure if this is your problem, but you should also be clearing the depth buffer bit with your GL.Clear command.

Nice point MaxH, haven’t seen it…

I use the Clear command. I’ll investigate how to create the window with depth buffering enabled…

I added:

GL.Clear(Buffer.DEPTH_BUFFER_BIT);
GL.DepthMask(GLFeature.TRUE);
GL.DepthFunc(GLFeature.LESS);

And I made sure that I created my window with depth buffer enabled.

And guess what? It still doesn’t work. A reference to code that successfully implements basic hidden surface would be helpful…

Are you sure this command is correct? Is it ‘DepthTest’?
In my flavor of OpenGL it would be ‘GL_DEPTH_TEST’.
Check the spelling in your documentation.

MaxH, I’m sure. Since I’m using c#, I had to define the opengl constants. It’s the same as GL_DEPTH_TEST: 0x0B71.

What is interesting is that “GL.Enable(GLFeature.DepthTest);” definitely does something. Without it, triangle B is always on top. With it, triangle A is always on top.

I wonder: is it possible to think you are moving the camera but really be moving in some other way? I’m new to opengl, so I don’t have a good feel for how all the pieces fit together.

I wonder: is it possible to think you are moving the camera but really be moving in some other way?

Anything is possible. How are you specifying the various matrices? Or, since you’re new, are you specifying any matrices at all?

Ok, I solved it! The problem was with setting up the perspective. I had:

GL.Perspective(45.0, Window.Width / (float)Window.Height, 0, 200);

The problem is with the “0”. If I make it “.5”, hidden surface removal works!

Now my only questions is: why don’t manuals and tutorials tell you that to implement hsr you need to make sure x, y, z, … Instead they all basically say to enable depth testing and that’s it. Note to other newbies: if an opengl command doesn’t do what people say it’s supposed to do, it’s probably because it only works given certain other settings. And when people tell you “it’s simple. just do this,” keep in mind that these are experts who are probably assuming you know about these background settings…

Thanks everyone for all your helpful attempts. Hopefully, it will all be of value to someone else, too.

http://www.opengl.org/sdk/docs/man/xhtml/gluPerspective.xml states that zNear should never be set to zero.

If you look at the matrix generated, when zNear = 0, you get:


[ f/aspect  0  0  0]
[ 0         f  0  0]
[ 0         0 -1  0]   
[ 0         0 -1  0]

which when multiplied by a vector V = [x, y, z ,w] gives

[fx/aspect, fy, -z, -z]

and then dividing out the w term gives:

[fx/(aspectz), -f*y/z, 1]

So when zNear = 0, whatever values you put into V, you will always get 1 for the z (depth) value.

Without depth test enabled, whatever was drawn last will be rendered in front, but with depth test enabled, you were drawing two objects at the same depth, so which one appears would depend on the depth function, calling glDepthFunc with different values will make a different triangle appear in front.

Wisely put, Dan.

I’ve learned a helpful principle: if my opengl code doesn’t do what people say it should do, then it’s likely because I’ve either changed one of the default values or I’ve used another function incorrectly. That principle is very helpful to me (as it’s more specific than “I’ve failed to set things up properly”).

Thanks everyone for your patience.