7

On the GL wiki they recommend using GL_LEQUAL for the depth function. Also, the depth function defaults to GL_LESS. When I use either of these functions, I get strange results. In this picture the red square should be in front of the blue one (both squares are the same size): with GL_LESS

However, if I use glClearDepth(0.0) and then glDepthFunc(GL_GREATER), running the otherwise unchanged program I get this: with GL_GREATER

Thinking about it a bit more, it makes sense that GL_LESS would give the results it does: if the incoming depth value is less than the stored one, the fragment is written.

If I positioned my camera at (1, 0, 0) and looked towards (0, 0, 0) I expect an object at (0.5, 0, 0) to be in front of an object at (0, 0, 0). With GL_LESS wouldn't the object at (0, 0, 0) be the one whose fragments are written?

EDIT: Nicol, thanks for mentioning the projection matrix. It seems like it was set incorrectly. I was following your tutorial on arcsynthesis.org for awhile and adapting the code to my own project, but I deviated from your projection matrix and used math described on the glFrustum man page to implement my own version of that function, and then used NeHe's gluPerspective replacement to replace gluPerspective. I don't know why the replacements didn't work because my matrix math is correct (i have checked it against various online calculators). Using your matrix I get the correct result with GL_LESS.

user1175938
  • 285
  • 1
  • 3
  • 6
  • 3
    What is your depth range? The parameters you pass to `glDepthRange`. "the red square should be in front of the blue one " Can you post the code that shows that this is the case? The code that draws the squares and positions the camera, the perspective matrix, and everything else? – Nicol Bolas Jan 29 '12 at 22:44

2 Answers2

20

Why is GL_LEQUAL recommended for the GL depth function

Shaders. Multipass alphablended lightning (possibly with bumpmapping). To do that, you'll have to paint same object on same position/depth several time, but with different shader/blending parameters AND depth test should be enabled (depth writing can be disabled after 1st past). GL_LESS will cut out 2nd pass and every pass after that. GL_LEQUAL won't, and lighting will work properly.

GL_LEQUAL will not cause z-fighting by itself, z-fighting happens when you have two almost parallel polygons sharing almost identical location. Effect can be reduced by increasing depth buffer precision. In the past it could have been also reduced by using w-buffer (at least in DirectX), but AFAIK this feature isn't popular anymore.

In this picture the red square should be in front of the blue one (both squares are the same size):

Impossible to answer correctly without source code.

SigTerm
  • 26,089
  • 6
  • 66
  • 115
  • +1 : Nice explanation. Since english is not my native language, I think I got i wrong to put the z-fighting thing as a myth and failed to answer this question with overdraw techniques. – Sam Jan 30 '12 at 00:14
2

If I positioned my camera at (1, 0, 0) and looked towards (0, 0, 0) I expect an object at (0.5, 0, 0) to be in front of an object at (0, 0, 0). With GL_LESS wouldn't the object at (0, 0, 0) be the one whose fragments are written?

According to this link: http://www-01.ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.opengl/doc/openglrf/glDepthFunc.htm%23b5afa88027vbia,

The glDepthFunc subroutine specifies the function used to compare each incoming pixel z value with the z value present in the depth buffer." It is also stated that: "GL_LESS Passes if the incoming z value is less than the stored z value.

Here: the z value is distance from camera to the object. This results in the closer object to be drawn on the screen. This is also explained here: http://www.glprogramming.com/red/chapter10.html

I quote from the last link:

Depth Buffer

The depth buffer stores a depth value for each pixel. As described in "A Hidden-Surface Removal Survival Kit" in Chapter 5, depth is usually measured in terms of distance to the eye, so pixels with larger depth-buffer values are overwritten by pixels with smaller values. This is just a useful convention, however, and the depth buffer's behavior can be modified as described in "Depth Test." The depth buffer is sometimes called the z buffer (the z comes from the fact that x and y values measure horizontal and vertical displacement on the screen, and the z value measures distance perpendicular to the screen).

Jamil
  • 359
  • 1
  • 7