0

I'm recently playing with glPolygonOffset( factor, units ) and find something interesting.

I used GL_POLYGON_OFFSET_FILL, and set factor and units to negative values so the filled object is pulled out. This pulled object is supposed to cover the wireframe which is drawn right after it.

This works correctly for pixels inside of the object. However for those on object outline, it seems the filled object is not pulled and there is still lines there.

Before pulling the filled object:

  This is before I pull the filled object

After pulling the filled object:

  This is after I pull the filled object

glEnable(GL_POLYGON_OFFSET_FILL);
float line_offset_slope = -1.f;
float line_offset_unit = 0.f;
// I also tried slope = 0.f and unit = -1.f, no changes

glPolygonOffset( line_offset_slope, line_offset_unit );
DrawGeo();

glDisable( GL_POLYGON_OFFSET_FILL );  
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
DrawGeo();

I read THIS POST about the meaning and usage of glPolygonOffset(). But I still don't understand why the pulling doesn't happen to those pixels on border.

Community
  • 1
  • 1
Bello
  • 1
  • 1

1 Answers1

4

To do this properly, you definitely do not want a unit of 0.0f. You absolutely want the pass that is supposed to be drawn overtop the wireframe to have a depth value that is at least 1 unit closer than the wireframe no matter the slope of the primitive being drawn. There is a far simpler approach that I will discuss below though.

One other thing to note is that line primitives have different coverage rules during rasterization than polygons. Lines use a diamond pattern for coverage testing and triangles use a square. You will sometimes see software apply a sub-pixel offset like (0.375, 0.375) to everything drawn, this is done as a hack to make the coverage tests for triangle edges and lines consistent. However, the depth value generated by line primitives is also different from planar polygons, so lines and triangles do not often jive for multi-pass rendering.

glPolygonMode (...) does not change the actual primitive type (it only changes how polygons are filled), so that will not be an issue if this is your actual code. However, if you try doing this with GL_LINES in one pass and GL_TRIANGLES in another you might get different results if you do not consider pixel coverage.

As for doing this simpler, you should be able to use a depth test of GL_LEQUAL (the default is GL_LESS) and avoid a depth offset altogether assuming you draw the same sphere on both passes. You will want to swap the order you draw your wireframe and filled sphere, however -- the thing that should be on top needs to be drawn last.

Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106
  • `+1`, the mention of different coverage rules is very interesting, I didn't know about that. – Bartek Banachewicz Jan 08 '15 at 11:59
  • Thanks for the reply. Yes I'm using GL_TRIANGLES for both cases, so the different coverage rules issue don't apply here. I'm not going to stick with glPolygonOffset. It seems to be unpredictable. – Bello Jan 08 '15 at 22:53