How do you draw nice thick lines?

I find it’s hard to draw really nice 3D lines that:

  • are thick (e.g. glLineWidth(10))
  • have smooth connected line pieces
  • can be rotated with constant thickness
  • can be transparent (difficult to realize when the gaps the inner vertices are smoothed by added points)
  • is good antialiazed…

I tried a lot, and the results aren’t satisfying. What’s your recommendation?

ravo

Sorry if the question seems to be too simple for the advanced coding forum, but I guess to get nice lines it needs advanced knowledge.

It’s not super-advanced, but non-trivial to get right. A thick line can be easily implemented by creating a tri-strip along the path, where every pair of points (one “above” the line, one “below”) is displaced by +/- a displacement vector, defined as the line segment’s perpendicular vector, normalized, and scaled to 1/2 the desired thickness of your line.

In 2D, perpendicular is simple. In 3D, you need more information. If you want your thick line to lie flat on the ground, find the displacement vector such that it is most perpendicular to the line segment and the up vector. For screen-aligned lines, use the camera “at” vector for creating a perpendicular (much like billboards).

So far, this only handles the case of one thick line segment (4 pts). Given two lines coming together at an angle, you have some options for how to handle the corner:

You can average the two displacement vectors, which works for fairly smooth curves but isn’t good for sharp corners (this meeting point can be “projected out” to the right place based on the dot product of segments, but still fails approaching 180 degree bends).

You can use two pairs of points, one for the end of segment A and set for the the start of segment B and let the tristrip rendering span the gap.

Or you can build a nice curved fillet, which is easily enough done by adding N pairs of points to the tri-strip between your straight bits, interpolating from the end angle of segment A to the start angle of segment B in the line’s plane. This looks best, but adds many more points than the original line.

Antialiasing is normal polygonal edge antialiasing in this case. But note the line can be antialiased out of view if it’s too thin. You may want to draw a linewidth=1 line first to ensure visibility.

Hope that helps.

Try

glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
glEnable(GL_LINE_SMOOTH);

:slight_smile:

Greetz,

Nico

Cyranose method’s is called “Polyline quadstrip”, and is imo the best way to render enhanced 3D lines.

My website has some 2 years old screenshots of what it gives when you add some textures.
http://www.succubus.fr and then go in the “Medias” menu, then “Galeries”, and then scroll down to "Rendus Non-Photoréalistes
" and find the black and white shots.

SeskaPeel.

And I forgot to recommend again Eric Lengyel’s book, that explains all the maths behind this.
He’ll surely add a link to his webpage, I’m too lazy to find it back.

SeskaPeel.

GL_LINE_SMOOTH is definitely not a good solution because:

  1. the number of subpixel bits varies widely across renderers, from 0 to 8
  2. some renderers don’t take the angle of the line into account and thus the thickness is wrong, and the endcaps are always vertical or horizontal instead of perpendicular to the line
  3. the GL spec says linestrips are treated as groups of line segments. there’s no handling of segment joining or mitering.

Many thanks for replies, folks! Your answers help me finding the direction… I’ll try to realize the triangle strip based method proposed by Cyranose.

ravo