PDA

View Full Version : Selected edges always in front



devdept
11-05-2009, 02:56 PM
Hi Everybody,

New post old problem:

How can we make selected edges to stay ALWAYS in front of blue ones during 3D rotation (picture A) instead of flickering all the time (picture B) ?
http://www.devdept.com/edges.jpg
Please don't suggest disabling depth test during edge drawing because in a more complex part they won't be hidden from polygons. Clearly to get this result we are already using polygon offset to make edges always to stand out.

Thanks,

Alberto

AdrianPi
11-05-2009, 03:28 PM
Use GL_LEQUAL and draw selected edges after the non-selected ones.

glDepthFunc(GL_LEQUAL)

// draw non selected edges

// draw selected edges

DmitryM
11-05-2009, 03:30 PM
Maybe I'm missing something, but why not just draw the yellow polygon's edges with a bigger offset?

devdept
11-05-2009, 03:36 PM
I really wish you were right DandyYuyo, I will try ASAP your solution.

Shall I restore a standard depth func after these calls, right?

Thanks,

Alberto

devdept
11-05-2009, 03:38 PM
Dimitry,

The polygon offset only offset poligons, not wires.

Alberto

DmitryM
11-05-2009, 03:52 PM
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glEnable(GL_POLYGON_OFFSET_LINE);
glPolygonOffset(1.0f,1.0f) //or higher
//draw some polygons as wires with offset

AdrianPi
11-05-2009, 03:56 PM
You should if that's what you need. I normally use GL_LEQUAL all the time as "default" to enable multiple passes.

The caveat with PolygonOffset is that units and factor is driver dependant, and you may have problems with too far or too near objects.

GL_LEQUAL solution guarantees that fragments with same depth values pass the depth test on any hardware unless the implementation really sucks. Draw your selected edges with exactly the same coordinates and order as the non-selected otherwise it may not work.

You have GL_POLYGON_OFFSET_FILL, GL_POLYGON_OFFSET_LINE, or GL_POLYGON_OFFSET_POINT, so you can offset polygons, lines or points.

Brolingstanz
11-05-2009, 04:03 PM
Sadly lines and polygons don't make good bedfellows. No amount of depth offset is going to save you in the pathological cases. Check out NV's solid wireframe demo for a great way to skirt the depth buffer business.

devdept
11-05-2009, 04:07 PM
Wow, I completely forgot the other two ones. By the way I guess that the offsetting polygons away from the viewer or edges closer to the viewer is the same right?

I was wondering if these two approachs differs when I rotate the box and the selected face is behind the others...

Thanks again,

Alberto

devdept
11-05-2009, 04:10 PM
Brolingstanz,

I tried to google for Nvidia Solid Wireframe demo without success, can you provide a link?

Will this approach work also on legacy GPUs?


Thanks,

Alberto

DmitryM
11-05-2009, 04:25 PM
The caveat with PolygonOffset is that units and factor is driver dependant, and you may have problems with too far or too near objects.

Not more driver-dependent than any other OpenGL feature. The amount of offset is strictly defined in the specification and depends only on the depth buffer resolution (that can be specified manually by you).



GL_LEQUAL solution guarantees that fragments with same depth values pass the depth test on any hardware unless the implementation really sucks. Draw your selected edges with exactly the same coordinates and order as the non-selected otherwise it may not work.

If 'bad' edges fragments had the same depth values - there would be no flickering during rotation. I doubt LEQUAL will help here.

AdrianPi
11-05-2009, 05:18 PM
Hi Dmitry,

żDid I get it wrong or he's asking how to overdraw edges?

I assumed that he has a list of edges, and not that is doing glPolygonMode(xxx, GL_LINE).

Then if we wants selected edges to be drawn over all edges already drawn in blue, GL_LEQUAL (or even GL_EQUAL) will suffice for that.

He can also NOT DRAW non-selected edges in blue in the first place!

*OR* he can do GL_POLYGON_OFFSET_LINE and suffer from z-fighting in some "pathological cases" as Brolingstanz pointed out.

Finally yes, he can do wireframe with shaders and in a single-pass but it won't work with legacy hardware:

http://orbit.dtu.dk/getResource?recordId=219956&objectId=1&versionId=1

devdept
11-06-2009, 02:51 AM
Hi DandyYuyo,

Here is the result: no improvement.

Quick movie (http://www.screencast.com/t/u3GOSdgyc)

I added the glDepthFunc(GL_LEQUAL) before I draw edges (first non selected then selected) and glDepthFunc(GL_LESS) at the end to restore defaults.

In this case we are *not* using glPolygonMode(xxx, GL_LINE) to draw edges but it happens in other situations.


What I am doing wrong?


Thanks,

Alberto

AdrianPi
11-06-2009, 08:27 AM
For what I can see in the video, you may be suffering because of those "T" vertices. Are you sure edges in the unselected polygon are exactly the same the as the ones in the selected polygon?. Do you have the same z-fighting with a simpler shape, such as a cube?

In other words, do the polygons really share the edges?

If they don't and this is a requirement in your application, then do as dmitry says. Use PolygonOffset with GL_POLYGON_OFFSET_LINE to offset selected edges towards the camera. But I would suggest you to avoid "T" vertices.

devdept
11-07-2009, 03:45 AM
They aren't 'T' vertices, planar faces are triangulated without splitting edges. I don't understand by the way a 'T' vertes should affect in some way the depth buffer.

I will also try Dimitry solution.

Thanks,

Alberto

devdept
11-07-2009, 04:11 PM
The sad news is that depending on the object we are drawing, edges are drawn either using GL_POLYGON_OFFSET_LINE or GL_LINE_STRIP :(. This is the reason why we can only push triangles away from the viewer.

I am sure that another trick that works in our scenario exists.

Any other idea?


Thanks,

Alberto

DmitryM
11-09-2009, 07:44 AM
either using GL_POLYGON_OFFSET_LINE or GL_LINE_STRIP

I don't understand: the GL_POLYGON_OFFSET_LINE is a OpenGL state, while GL_LINE_STRIP is a drawing mode.
Moreover, AFAIK, you can pass negative values into the PolygonOffset() making the triangles/edges closer to the viewer.

devdept
11-09-2009, 07:54 AM
Dimitry,

You are right I wrote the wrong GL_ code, sorry.

In some cases we draw edges simply redrawing the polygons with the glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) in some others we draw edges with glBegin(GL_LINE_STRIP).

This is *the reason* why we cannot used different negative offset values into the glPolygonOffset() function. They would affect only the edges drawed using glPolygonMode(GL_FRONT_AND_BACK, GL_LINE), not the others. Is this correct?


Thanks,

Alberto

DmitryM
11-09-2009, 08:31 AM
Maybe it's too late, but here is a short FAQ:
http://www.opengl.org/resources/faq/technical/polygonoffset.htm

So, you have 3 kind of primitives drawn:
-polygons
-lines drawn as edges using PolygonMode()
-lines drawn simply via GL_LINE_STRIP

You can vary 2 of these depth offsets, so you have a full control over all(3) their *relative* offsets.

wSpace
11-09-2009, 01:29 PM
I believe you could do what you want by using the stencil buffer.

1. Enable depth test.
2. Draw the non-selected sides (and any other geometry).
3. Enable the stencil test.
4. Draw the selected side, and set the stencil buffer to 1 where the selected side "wins" the z-buffer test.
5. Disable the stencil test.
6. Draw the edges (lines) that surround the non-selected sides.
7. Disable depth test.
8. Enable the stencil test.
9. Draw the edges (lines) that surround the selected side, but only where the stencil buffer is set to 1.

This technique requires that your line width be larger than 1. In your screen shot, it looks like your lines have thickness. Not sure if you mind, but the selected lines will only draw where they overlap the selected side, i.e., the lines will not bleed outward beyond the selected side.

The stencil is set to 1 only where the selected side "won" the z-buffer test. So, the selected lines will draw only where they are visible. Since the selected lines are drawn without depth testing, you won't have z-buffer fighting with the other lines.

You could use this idea to correct z-buffer fighting between the non-selected faces and edges if you chose not to use a polygon offset.

AdrianPi
11-09-2009, 07:01 PM
In some cases we draw edges simply redrawing the polygons with the glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) in some others we draw edges with glBegin(GL_LINE_STRIP).

That's why GL_LEQUAL or GL_EQUAL doesn't work. As you are using different primitives to draw your edges, there is no invariance guaranteed.

devdept
11-10-2009, 02:04 AM
wSpace,

Why this approach should work only for thickness bigger than one? The edges thickness is a parameter in our app and can be even one.

Thanks,

Alberto

wSpace
11-10-2009, 08:04 AM
wSpace,

Why this approach should work only for thickness bigger than one? The edges thickness is a parameter in our app and can be even one.

Thanks,

Alberto

Imagine that your selected line width is set to 2. When a line is drawn between two vertices, half the line overlaps the selected side and the other half is off of the side. Because the line only draws where the stencil buffer is set to 1, which is where the selected side is, you will only see half of the line; it would appear that the line is one pixel wide.

My thought was that if you tell OpenGL that you want a line width of 1, you would see a line width of 0.5, which might look broken up.

This really isn't a problem. If the user wants to see a line width of 1, you really tell OpenGL that you want a line width of 2. You just double the user's preference.

The best thing might be to try out this technique to see if the visual quality is what you're looking for.

AdrianPi
11-10-2009, 06:47 PM
Hello Alberto,

http://i34.tinypic.com/2jdhop5.png

Here I'm overdrawing selected edges with GL_LEQUAL. The trick is that selected and non selected edges are specified with the same primitive (GL_LINES) and with the vertices in the same order. That way OpenGL produces exactly the same depth values for the fragments, and the depth test, with GL_LEQUAL (could be GL_EQUAL aswell) passes.

So in a first pass I draw polygons (GL_TRIANGLES) with polygon offset. Then I draw all edges (and vertices).

After I overdraw selected edges with GL_LEQUAL but GL_EQUAL should work too.

The reason of why I use GL_LEQUAL is that I GL_LEQUAL all the time to allow for multiple passes.

devdept
11-11-2009, 01:05 AM
Thanks wSpace,

I will try this approach ASAP.

Alberto

devdept
11-11-2009, 01:07 AM
DandyYuyo,

Nice result, my best compliments. This is exaclty what we are trying to achieve. BTW I can use it because we use different approached to draw edges.

Alberto