tags:

views:

1932

answers:

6

I'm trying to a draw a more-or-less smooth multi-segment line in OpenGL. However I find that if the line is over a thickness about 3 then the joins between the segments are not seamless. They sometimes have gaps between them. Is there a good way of making these joins smooth and gapless? I'm looking for something like the equivalent of BasicStroke.JOIN_MITER in Java.

A: 

overdraw the lines by half the thickness on each end. That should remove the 'gaps' although it'll give a sharper line join rather than a smoother one.

workmad3
+1  A: 

Depending of the quality of the OpenGL implementation, the results may vary. I've noticed a lot of differences for smooth lines on different implementations.

You may want to use a different strategy to draw your line segments, such as using thin polygons.

Martin Cote
Thin polygons seems attractive, but I also need to be able to use antialiasing and stipples.
DJClayworth
It's possible to antialias polygons, and glPolygonStipple does exist.
Andrei Krotkov
I didn't know that. It might be helpful.
DJClayworth
It turns out polygon stipple isn't quite the same as line stipple. I think I'm going to have to go with polygons for solid lines and use the renderers own line drawing for stippled lines, where the defects are not quite so obvious.
DJClayworth
+1  A: 

Enabling anti-aliasing with GL_LINE_SMOOTH changes the way lines are drawn slightly. You may try that. Also note that blending will need to be enabled for that to work.

The main thing is that you're not going to be able to control every aspect of how lines are drawn using thin rectangles might work better, and after you write your own DrawThickLine function it won't be any more work...

JPhi1618
I already tried GL_LINE_SMOOTH, and it gives different, but not unfortunately better, results.
DJClayworth
Another thought -- Can you just plot GL_POINTS and GL_LINES? The points should cover up any spacing problem you have, and if you used GL_POINT_SMOOTH, they are rendered as round circles instead of boxes.
JPhi1618
Another good idea, but it turns out that some renderers make a line thicker by extending it only on one side. The points are not centered on the line when both are thick.
DJClayworth
Wow, I have not ran into that, but I'll take your work for it. Seems like a dumb way to make a line thick... Thumbs down for that idea.
JPhi1618
A: 

To get something smooth you may want to resort to Bezier curves or some other form of splines. I'm surprised this isn't built into OpenGL, but the web site has an example program to generate Bezier curves using OpenGL.

Norman Ramsey
The problem here is not the curviness of the lines, but that the ends of the segments don't match up against each other, even if they are supposed to be straight segments.The program still ends up sending line segments to OpenGL and we are back where we started.
DJClayworth
Bletch. I'm tempted to downvote my own answer (losing 3 reputation)...
Norman Ramsey
+3  A: 

The most consistent and portable way to draw think lines using OpenGL is to use camera aligned (otherwise know as billboarded) polygons. Different implementations of the OpenGL API handle the end points of the lines differently and GL_LINE_SMOOTH produces drastically different results depending on the platform. Some implementations consider lines of thickness greater then 1 to be ill-defined. As stated in the glLineWidth manpages: [For anti-aliased lines] only width 1 is guaranteed to be supported; others depend on the implementation.

That being said, I have used a simple 2 pass hack to address this very problem.

  1. Disable writing to the depth buffer glDepthMask(GL_FALSE)
  2. Draw smoothed lines of desired thickness
  3. Draw smoothed points at the endpoints of all the lines that are the same size at the lines. (this step may not be needed to fill the gap, however it should round out the points where the lines meet and make everything look a little smoother)
  4. Re-enable the depth buffer for writing glDepthMask(GL_TRUE)

You may also want to play around with the depth buffer settings. The "gap" between the lines may be due to the 2nd line failing a depth test on pixels that have been alpha blended with the background.

Marc
On some renderers thick lines are drawn by extending the line in one direction only. In that case the points are not drawn in the centre of the line. It seems OpenGL really doesn't handle this very well. I think polygons are going to end up being the best way.
DJClayworth
A: 

Draw quads, and use a texture or a fragment shader to stipple. A fragment shader could also provide antialiasing.

Bananadine