Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL : thick and smooth/non-broken lines *in 3D*

I have a 3D CAD-like application for which I use OpenGL wrapper library (OpenSceneGraph). For the application I am trying to come up with the best strategy on how to render thick and smooth lines in 3D.

By thick and smooth I mean:

  • line thickness can be more than OpenGL maximum linewidth value (it seems to be 10.f on my machine)
  • when composing polylines I want to avoid the look of "broken lines" (see example image below)

OpenGL <code>LineStrip</code> looks broken, zoomed-in image

At the moment I render my polylines by using GL_LINE_STRIP_ADJACENCY.

I found there are many different resources on how to render nice looking lines and curves in 2D. The simplest approach that does not require much thinking is to render the line as a set of quads (GL_QUAD_STRIP). The good thing about this solution is that it solves both of my problems at the same time.

As an example, I also found this nice library that allows to achieve wide range of line and curve looks. It uses triangles for rendering.

Note: I do not seek for fancy effects like per-vertex coloring or brush-like strokes, just a 3D line segment that can have large thickness and that connects well with another line segment without any gaps between them.

The problem with those 2D approaches is that they are 2D. When I change the view point, it is obvious my line geometries are not lines but rather 2D "ribbons" lying in certain 3D planes. And I want them to look like 3D lines.

When thinking about the problem, I could only come up the the following approaches:

  1. Render line as a set of 2D quads (triangles) and then make them to always face the camera
  2. Use some 3D shape like cylinder to represent a line segment

I am not sure how feasible any of the two solutions are (I am beginner in OpenGL). I might have hundreds or even thousands of polylines on the scene. I am also wondering if there is a better, smarter way to approach the problem? I am open to anything and interested in the most efficient way. Thank you.

EDIT: as pointed by user @rickyviking, I didn't clarify explicitly that I am going after a 2D look (like in any CAD-like app) which would mean: the thickness of the lines does not depend on how far/near the camera is located from them.

UPDATE: thanks for answer of @rickyviking, I chose the direction to move with - geometry shaders. I still do not have a complete solution, but might post a final update and minimal code when the result is achieved, here.

like image 838
vicrucann Avatar asked Dec 05 '22 18:12

vicrucann


1 Answers

I ended up using geometry shader as was suggested by one of the answers. The main idea was to convert every line segment into a triangular strip and to make sure that it always faces the camera and thickness remains the same.

I also wrote a blog post about the implementation details. If someone finds it useful, I placed the shader codes on one of my github repos (the code also provides example on how to draw thick and smooth Bezier curves using the same technique).

Here are some result screenshots (green lines are drawn using the shaders, red are by using GL_LINE_STRIP_ADJACENCY):

same thickness example

bigger thickness example

Note the gaps between the adjacent line segments of the red lines compared to the green ones.

Two Bezier curves (all drawn using the shaders):

Bezier curve examples

like image 104
vicrucann Avatar answered Jan 01 '23 18:01

vicrucann