Dotted or dashed polylines using geometry shaders

I had an idea for dotted polylines using geometry shaders and wanted some feedback on whether it was crazy before proceeding.

First for a single line you would:

  • Pass the points using GL_LINE_STRIP_ADJACENCY
  • Calculate the screen space used by the line
  • Calculate, for a given line width and point spacing, how many points fit in that screen space
  • Generate the point geometry for the calculated number of points

At this level I see a couple of problems:

  • The number of vertices is dependent on a calculated value. This is probably bad for performance…but i’m not sure how bad.
  • If the line is long, the number of points generated might exceed max vertices. Perhaps this can be mitigated by clipping the line to the screen.

The advantages:

  • No precalculated vertex data required.

So on to polylines.

  • If you naively apply the previous algorithm to a polyline you have the issue that the pattern doesn’t continue correctly across adjacent lines. For longer lines it might not look horrible, but for anything dense you’ll end up with a ton of overlap.

Here’s where the crazy(?) part comes in:

  • Do a first pass where you calculate the screen space length of each segment of the polyline and store that in a float texture.
  • Do a post-process on that texture such that the each texel gives the distance from the start of the polyline (not exactly sure how to do this yet)
  • Finally, use the point indices and the phase from the texture to determine which, if any, points need to be generated.

Again, the advantage is there’s no preprocessing.

Disadvantages include a dependent texture lookup. I’m not sure how bad that is in this case, but my understanding is that generally such things are “bad”.

Finally, I think such an approach could also be used with an sdf pattern as an alternative to generating individual points/dashes. This I think could have several advantages…but again it depends on the viability of the approach for determining the phase for a line segment. Or maybe there’s a better approach altogether for that.

Ignore my post if you already try that:
Use 1D decal texture of your dotted or dashed pattern. The texture coordinate is the sum of world space distance or squared distance from the start (multiplied by a scale factor if needed) of the poly line between two adjacent vertex. Use texture repeat mode.

Parallel prefix sum. Only worth doing on the GPU if you have many line segments or if the vertex positions are calculated on the GPU. Otherwise it’s better to just perform an iterative calculation on the CPU and include the accumulated distance as a vertex attribute.

I came up with this somewhat naive approach which consists in mapping the polylines in screen space: Shader - Shadertoy BETA

It’s prone to artifacts and the result is not perfect, however, it doesn’t require any pre procrssing and looks nice enoughfor some use cases.