# Rendering splines on GPU

We have an application which needs to render spline curves (cubic, bezier, b-spline etc.). We currently have working algorithms in C to stroke the control points of these curves into line strips.

The issue we are running to is the need to constantly re-stroke the curves based on zoom and how much of the curve is visible. I am guessing this would be both more practical and more efficient to do on the GPU.

What is the most standard way to approach this problem? I have heard about Geometry shaders but have also heard they are inefficient so I'm not sure if there is maybe a better way. If not, what is the general process of stroking curves like this?

In general, the stroking algorithms take in the control points of the curves, and determine a new set of points for a line strip (based on a tolerance calculated from the zoom level, which defines the stroking interval).

We are using Vulkan if it makes any difference. Thanks!

• You can draw the curve with shaders on a plane. Oct 17, 2021 at 18:29
• Do the curves have a thickness that will be zoomed as well ?
– user1703
Mar 14, 2023 at 13:23
• You should read on the topics of curve flattening and curve offsetting.
– user1703
Mar 14, 2023 at 13:24
– lhf
Nov 10, 2023 at 0:24

It should be reasonably easy to implement a line segment based spline shader using just a vertex shader and fragment shader. The biggest issues are how the splines are represented, getting that data to the GPU, then writing a vertex shader that accesses the correct spline info.

As one possibility:

1. Upload the spline info to an appropriate buffer.
2. Setup a graphics pipeline to draw lines.
3. Setup the vertex shader to take a push constant which holds info about which spline to use and other relevant info.
4. Then do a draw call with the number of line segments needed for the final spline, along with appropriate push data.

Since the pipeline is expecting lines every two vertices represent 1 line segment. The vertex shader can use the vertex index (made available through glsl) to determine which segment to draw. IE 0, 1 are segment 0: 2,3 are segment 1. Combined with the push data it can lookup the spline values, compute the segment vertex data, do the appropriate MVP transform for each end of that segment.

The upside is each spline can have a variable number of segments such as a draw call for a spline with 256 vertices would get 128 segments. The vertex shader can also determine line width which could be varied if the splines are 3D to make them thicker as they move away from the camera.

But the ends of the splines could be tricky to get connected smoothly, as the line segments change direction there could be overlap and disjoint looking spots on the splines. (it really depends on the line thickness)

Computing a segment that is equally spaced on splines isn't very easy but is doable.