Not logged in, Join Here! or Log In Below:  
 
News Articles Search    
 

 Home / 3D Theory & Graphics / Problem with Z-buffer and glPolygonOffset Account Manager
 
Archive Notice: This thread is old and no longer active. It is here for reference purposes. This thread was created on an older version of the flipcode forums, before the site closed in 2005. Please keep that in mind as you view this thread, as many of the topics and opinions may be outdated.
 
Cygnus

April 18, 2005, 08:04 AM

Hi!

I have 2 rendering passes, one (the first) to the depthbuffer/z-buffer and the second to render the actual points. I need to offset the values in the z-buffer a bit during the first pass, so that only the points closest to the viewer are rendered during the second pass.

I'm using GL_POLYGON_OFFSET_POINT as suggested by someone here, but it isn't working. I don't know what I'm doing wrong. Changing the 2nd parameter of glPolygonOffset() seems to have no effect. I always get a black screen, unless I uncomment "//glDisable(GL_DEPTH_TEST)" in the 2nd pass. In that case everything is rendered (screenshot 2).

Here's my code :

  1.  
  2. //////////////////////////////////////////////////////////////////////////
  3. //FIRST PASS
  4. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  5. glEnable(GL_DEPTH_TEST);
  6. glDepthMask(GL_TRUE);
  7. glDepthFunc(GL_LESS);
  8.        
  9. glEnable(GL_POLYGON_OFFSET_POINT);
  10. glPolygonOffset(1., 0.01);             
  11.        
  12. cgGLBindProgram( m_cgVertex1stPassProg );
  13. cgGLBindProgram( m_cgFragment1stPassProg );
  14.        
  15. glDrawArrays(GL_POINTS, 0, m_nNrOfPoints);     
  16.  
  17. //////////////////////////////////////////////////////////////////////////
  18. //SECOND PASS
  19. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  20. glDepthMask(GL_FALSE);
  21. //glDisable(GL_DEPTH_TEST);
  22.        
  23. glDisable(GL_POLYGON_OFFSET_POINT);
  24. glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
  25. glEnable(GL_BLEND);
  26. glEnable(GL_ALPHA_TEST);
  27. glAlphaFunc(GL_LEQUAL,1.0);
  28.        
  29. cgGLBindProgram( m_cgVertexProg );
  30. cgGLBindProgram( m_cgFragmentProg );
  31.        
  32. glDrawArrays(GL_POINTS, 0, m_nNrOfPoints);
  33.  


Here's a screenshot of my depthbuffer :
http://img49.echo.cx/img49/678/framedepth01000066post2or.jpg
Here's a screenshot of my framebuffer (if GL_DEPTH_TEST is disabled during the 2nd pass, otherwise I always get a black screen) :
http://img167.echo.cx/img167/1047/framecolor01000066post4in.jpg

As you can see in the 2nd screenshot, all points are blended, even the ones in the background, that should be culled by the z-buffer test.

Does anyone know how I can make the z-buffer test work for me?
Any help is more than appreciated!

Cygnus.

 
Reedbeta

April 18, 2005, 03:09 PM

Forget about polygon offset; just use glDepthTest(GL_LEQUAL).

 
Cygnus

April 18, 2005, 03:18 PM



Reedbeta wrote: Forget about polygon offset; just use glDepthTest(GL_LEQUAL).


The depth values have to be offset a bit, so that the points closest to the viewer AND the points close to those points are drawn. GL_LEQUAL alone won't do the trick.

 
grelle

April 18, 2005, 04:54 PM

I believe you want to set the first parameter to 0 in this case. And, you might want to add the offset to the second pass, not the first.

According to documentation:
"glPolygonOffset(GLfloat factor, GLfloat units);
The value of the offset is factor * dz + r * units, where dz is a measurement of the change in depth relative to the screen area of the polygon, and r is the smallest value that is guaranteed to produce a resolvable offset for a given implementation. The offset is added..."

As I understand the above you must specify a value > 1 on the second parameter to get an effect, since: "r is the smallest value that is guaranteed to produce a resolvable offset"

 
Cygnus

April 19, 2005, 08:37 AM

If I use glDepthTest(GL_LEQUAL) like Reedbeta suggested, I only see the nearest points, which is only a thin layer, because I need the group of points that are close to the viewer.

grelle : I don't see how adding the offset during the 2nd pass instead of the 1st will work, but I'll try...

 
grelle

April 19, 2005, 11:48 AM

"I don't see how adding the offset during the 2nd pass instead of the 1st will work"
No, it was a bad suggestion. =)
I thought for a moment that the z-buffer was 'inverted'

 
Reedbeta

April 19, 2005, 01:58 PM

I don't quite understand what you are trying to do...can you describe in more detail what is the "group of points close to the viewer" that you are trying to render? I don't see what would be the difference between the polygon offset method and glDepthTest(GL_LEQUAL).

I assume the points you've got are the vertices of the triangles of the bunny...if you're trying to render only points on the bunny's visible surface, you will need to draw the bunny into the depth buffer using polygons, not points, so as to ensure that all the "background" points will be occluded.

 
Erik Faye-Lund

April 20, 2005, 03:59 AM

perhaps GL_LEQUAL isn't working due to shader invariance?

 
Cygnus

April 20, 2005, 06:37 AM

I'm using points to render the bunny. Every point is a gaussian splat, with its own radius (and normal). The gaussian splats are blended together, to get a smooth, anti-aliased surface. I'm rendering them with the GL_POINT-primitive and my fragment & vertex shader do the gaussian filtering.

So if my camera is in front of the bunny model and looking right at it, the "group of points close to the viewer" is the face and chest of the bunny, but not its back. So only the points that would be visible if I'd have an opaque surface. Because the splats overlap, I can't just use glDepthTest(GL_LEQUAL), but I need a small offset added to each z-value.

Here's a screenshot my bunny with all points rendered and no depthtest (notice the overlapping ears):
http://img210.echo.cx/img210/2163/screenshotnodepthtest2xm.jpg

And here's a screenshot with depthtest enabled and glDepthTest(GL_LEQUAL) :
http://img210.echo.cx/img210/76/screenshotdepthtest3yr.jpg

 
Morgan

April 20, 2005, 11:29 AM

Unfortunately, GL_POLYGON_OFFSET_POINT does not apply to GL_POINTS. It only applies to GL_QUADS, GL_TRIANGLES, etc. that are rendered with the point fill mode.

Two tricks I've used in the past to get around this are a vertex/fragment shader that computes a new depth offset and playing with glDepthRange. Note that glDepthRange and writing to gl_FragDepth will both disable early-out depth tests until the next glClear, which could seriously impact performance.

-m

 
Cygnus

April 20, 2005, 02:44 PM

Thanks Morgan, now I know why it wasn't working :)
What's the best way to "play with glDepthRange"?

Something like this?

  1.  
  2. glDepthRange(0.01,1.01);
  3. ... // first pass
  4.  
  5. glDepthRange(0.0,1.0);
  6. ... // second pass
  7.  



 
Reedbeta

April 20, 2005, 03:49 PM

"only the points that would be visible if I'd have an opaque surface."

It sounds to me like you could first render a SOLID bunny into the depth-buffer, using triangles (which you can depth-offset as you like). According to the code you posted above, you're using points in the depth pass as well as in the second pass.

 
Morgan

April 20, 2005, 05:35 PM

Yes, almost exactly like that,


double e = 0.01;
glDepthRange(e, 1);
... // first pass

glDepthRange(0,1-e);
... // second pass


Switch the order depending on which you want pushed forward.

-m

 
Cygnus

April 25, 2005, 09:16 AM

Thanks Morgan!

Rendering the model first using triangles would also work, yes, but I'm programming this for my thesis, where I have to "prove" that points (and points alone) can be used to render models with high quality and without artifacts.

 
Cygnus

April 27, 2005, 01:50 PM

It seems that it's better to use the fragment shader instead of glDepthRange in my case. So I need to get the value of the depth buffer by computing the eye-space z-coordinate (in my vertex shader) and applying viewport mapping to it (in my fragment shader). For some reason, it goes wrong :(

Right now I do this in my vertex shader :

  1.  
  2. float eyeSpaceZPos = mul(ModelView,(IN.Position)).z;
  3. OUT.PreCalculatedValues.z = eyeSpaceZPos; // passed on in texture coordinates
  4.  


And this in my fragment shader :
  1.  
  2. struct PixelOut
  3. {
  4.         half4 Color : COLOR;
  5.         half Depth : DEPTH;
  6. };
  7.  
  8. PixelOut main(vertexOutput IN, const uniform float a, const uniform float b )
  9. {
  10. ...
  11.  
  12. float zeye_dz = IN.PreCalculatedValues.z + offset;
  13. OUT.Depth = ((a * zeye_dz) + b) / zeye_dz;
  14. }
  15.  

where a and b are passed as parameters. a is f / (f - n) and b is -2 * n * f / (f - n), where f and n are the far and near plane.

Can anyone help me?

 
Cygnus

April 28, 2005, 05:35 AM

Never mind the above post, I'll start a new thread, because it's a new subject.

 
This thread contains 16 messages.
 
 
Hosting by Solid Eight Studios, maker of PhotoTangler Collage Maker.