# Drawing paths using OpenGL: Polyline2D

**URL:** <https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405>\
**Category:** Useful Tools and Components\
**Created:** [January 23, 2019, 1:59am UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405 "2019-01-23T01:59:00Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![CrushedPixel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/crushedpixel/32/8654_2.png) [@CrushedPixel](https://forum.juce.com/u/CrushedPixel)\
**Post date:** [January 23, 2019, 1:59am UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/1 "2019-01-23T01:59:00Z")

</div>

Since rendering paths with `juce::Graphics` hasn’t been performant enough for my use case, and modern OpenGL doesn’t support drawing thick lines, I wrote [Polyline2D](https://github.com/CrushedPixel/Polyline2D), a library to generate a 2D mesh from a set of points.

This way, you can render thick paths blazingly fast using OpenGL!

Here’s what it looks like:

 ![11](https://us1.discourse-cdn.com/flex026/uploads/juce/original/2X/2/2da7f7d4d667cb328b2331b7f9b311a165826684.png)  
For demonstration purposes, the **generated mesh** is once rendered in **wireframe mode (light green)**, and once in **fill mode (transparent green)**.  
The red points show the **input points**.

It supports all join and end cap styles that JUCE supports as well.

For an **example JUCE application** , see [Polyline2DExample](https://github.com/CrushedPixel/Polyline2DExample).

---

<div class="post-metadata">

**Author:** ![dave96](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dave96/32/8487_2.png) [@dave96](https://forum.juce.com/u/dave96)\
**Post date:** [January 23, 2019, 8:36am UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/2 "2019-01-23T08:36:01Z")

</div>

Have you tried plugging this in to the JUCE OpenGL renderer?

This could be a game changer as the slowest thing in the GL rendering is the rath rasterisation. Great stuff!

---

<div class="post-metadata">

**Author:** ![matkatmusic](https://avatars.discourse-cdn.com/v4/letter/m/dfb087/32.png) [@matkatmusic](https://forum.juce.com/u/matkatmusic)\
**Post date:** [January 23, 2019, 8:56am UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/3 "2019-01-23T08:56:47Z")

</div>

A lot of your stuff in LineSegment.h could have been done with the juce::Line\<\> class, same for the stuff in Vec2.h replicating some of juce::Point\<\>. Was there a reason for reinventing the wheel, so to speak?

---

<div class="post-metadata">

**Author:** ![clarke](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/clarke/32/4790_2.png) [@clarke](https://forum.juce.com/u/clarke)\
**Post date:** [January 23, 2019, 9:31am UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/4 "2019-01-23T09:31:14Z")

</div>

@matkatmusic the library itself doesn’t seem to depend on anything but the standard library. Not even OpenGL. I guess maximum portability was a design decision.

Nice work @CrushedPixel! I wonder how much work it would take to create a class that takes any `juce::Path` and generate vertices for OpenGL? Maybe even provide appropriate initialisation/render/shutdown methods and handle the shaders internally?

---

<div class="post-metadata">

**Author:** ![CrushedPixel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/crushedpixel/32/8654_2.png) [@CrushedPixel](https://forum.juce.com/u/CrushedPixel)\
**Post date:** [January 23, 2019, 10:14am UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/5 "2019-01-23T10:14:14Z")

</div>

> [@matkatmusic](#):
>
> Was there a reason for reinventing the wheel, so to speak?

As @Clarke correctly guessed, my goal was to make a self-contained library without any external dependencies. We’re not in JS-land here 😃  
Though I don’t know for certain, as I’ve never used it, I believe you could also send these vertices into a Direct3D rendering pipeline, so you’re neither restricted to JUCE nor to OpenGL.

> [@Clarke](#):
>
> Nice work @CrushedPixel! I wonder how much work it would take to create a class that takes any `juce::Path` and generate vertices for OpenGL? Maybe even provide appropriate initialisation/render/shutdown methods and handle the shaders internally?

> [@dave96](#):
>
> Have you tried plugging this in to the JUCE OpenGL renderer?

Both of these are great ideas! After a quick look at the JUCE source code, it seems to me like I can use a `juce::PathFlatteningIterator` to break any `juce::Path` down into straight lines, which can then be sent into `Polyline2D`.  
I’ll give @Clarke’s idea a try, and if that works out, we can figure out how to plug this directly into JUCE. I’ll probably need some help on the second part, though.

---

<div class="post-metadata">

**Author:** ![matkatmusic](https://avatars.discourse-cdn.com/v4/letter/m/dfb087/32.png) [@matkatmusic](https://forum.juce.com/u/matkatmusic)\
**Post date:** [January 23, 2019, 10:16am UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/6 "2019-01-23T10:16:18Z")

</div>

PathFlatteningIterator can be kinda slow if your path is large, fyi

---

<div class="post-metadata">

**Author:** ![CrushedPixel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/crushedpixel/32/8654_2.png) [@CrushedPixel](https://forum.juce.com/u/CrushedPixel)\
**Post date:** [January 23, 2019, 10:23am UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/7 "2019-01-23T10:23:26Z")

</div>

Aw, that sucks. It’s surely not as bad as the rasterization’s performance though, is it?  
Besides, I have to break the path down into points _somehow_, so I’ll just go for the easiest approach for now.

---

<div class="post-metadata">

**Author:** ![CrushedPixel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/crushedpixel/32/8654_2.png) [@CrushedPixel](https://forum.juce.com/u/CrushedPixel)\
**Post date:** [January 23, 2019, 1:06pm UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/8 "2019-01-23T13:06:01Z")

</div>

Success!  
This is a `juce::Path` with multiple subpaths being rendered using OpenGL and Polyline2D:

 ![33](https://us1.discourse-cdn.com/flex026/uploads/juce/original/2X/b/b4dc14576789de8670b1e5d0e06befd5adeeddb8.png)  
I had to add support for closed paths to Polyline2D, but it all works smoothly now.

Here’s the source code: [Polyline2DPathRenderer](https://github.com/CrushedPixel/Polyline2DPathRenderer)

Here’s the relevant bit, converting the `juce::Path` into a mesh:

> <https://github.com/CrushedPixel/Polyline2DPathRenderer/blob/b8271ecfb51c1feb8f5305fbd94f4097b68b9203/Source/MainComponent.cpp#L79-L128>

@dave96 @jules If you want to use my source code to integrate this into JUCE to speed up Path rendering (at least when using OpenGL), you have my full permission to use and/or modify the code of both Polyline2D and Polyline2DPathRenderer however you need.

---

<div class="post-metadata">

**Author:** ![matkatmusic](https://avatars.discourse-cdn.com/v4/letter/m/dfb087/32.png) [@matkatmusic](https://forum.juce.com/u/matkatmusic)\
**Post date:** [January 23, 2019, 9:14pm UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/9 "2019-01-23T21:14:28Z")

</div>

![](https://us1.discourse-cdn.com/flex026/uploads/juce/original/2X/d/d7dcc684cd9c0735a2d2e38725b004f86022351a.gif)

---

<div class="post-metadata">

**Author:** ![SQUARESEQUENCE](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/squaresequence/32/22364_2.png) [@SQUARESEQUENCE](https://forum.juce.com/u/SQUARESEQUENCE)\
**Post date:** [February 4, 2019, 1:37pm UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/10 "2019-02-04T13:37:56Z")

</div>

How would one go about comparing the performance between drawing paths this way and using Juce paths ? (I’m a bit new to OpenGL (and xcode for that matter)).  
I ask because I’m a bit hesitant (for now) just making a Juce path version of this example and then just comparing the CPU % from xcode’s debug session (is this cpu gauge accurate for this purpose ? )

Many thanks

Edit: as I suspected, the CPU reading on my end was strangely too high due to some bug with the current sdk ? (as read in this thread: [GUI Drawing Efficiency](https://forum.juce.com/t/gui-drawing-efficiency/15429/13)). So I guess my question still stands about how one would recommend profiling this example against a normal Juce example. I’d be happy to work up a repo and upload it when I’m done. I’m kinda really keen to find out if it’s worth learning OpenGL to do my GUI (simple animated shapes but a high number of simultaneous shapes - MIDI sequencer app)

---

<div class="post-metadata">

**Author:** ![CrushedPixel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/crushedpixel/32/8654_2.png) [@CrushedPixel](https://forum.juce.com/u/CrushedPixel)\
**Post date:** [February 4, 2019, 4:04pm UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/11 "2019-02-04T16:04:18Z")

</div>

The way I profile my GUIs is by using XCode’s Instruments program.  
I use the Time Profiler, record for a couple of seconds, and see how much time (relative to other functions) is spent inside the function responsible for rendering the paths. But if you have a sufficient amount of points in your path, the performance difference should be obvious by the amount of FPS you get - I got barely 10-15 FPS when using a JUCE path with ~200 points (rendering a waveform), but with Polyline2D I get 60FPS.

In general though, you should try to avoid switching over to OpenGL if possible at all - I’ve had to implement a fairly complex graphical component in OpenGL because of Path performance, and let me tell you, it’s nowhere near as simple as calling `graphics.drawRect` and friends. You have to prepare VAOs and Shaders, fill VBOs with vertices, generate and assign textures to the vertices, etc etc…

If you need any help though, feel free to DM me - I’ve created some neat OpenGL helper classes I can share with you, and will gladly help you with all of the tricky bits 🙂  
This tutorial helped me a lot: [https://learnopengl.com/](https://learnopengl.com/)

---

<div class="post-metadata">

**Author:** ![SQUARESEQUENCE](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/squaresequence/32/22364_2.png) [@SQUARESEQUENCE](https://forum.juce.com/u/SQUARESEQUENCE)\
**Post date:** [February 4, 2019, 4:37pm UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/12 "2019-02-04T16:37:48Z")

</div>

just DM’ed. This is great stuff for the Juce community.

---

<div class="post-metadata">

**Author:** ![tadnicol](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/tadnicol/32/5141_2.png) [@tadnicol](https://forum.juce.com/u/tadnicol)\
**Post date:** [February 13, 2019, 10:02pm UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/13 "2019-02-13T22:02:46Z")

</div>

This is fantastic thanks so much for making this! Can this be easily adapted to draw filled paths as well?

---

<div class="post-metadata">

**Author:** ![CrushedPixel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/crushedpixel/32/8654_2.png) [@CrushedPixel](https://forum.juce.com/u/CrushedPixel)\
**Post date:** [March 8, 2019, 10:09am UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/14 "2019-03-08T10:09:19Z")

</div>

Not yet, but I’ll have a look at that today.

---

<div class="post-metadata">

**Author:** ![CrushedPixel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/crushedpixel/32/8654_2.png) [@CrushedPixel](https://forum.juce.com/u/CrushedPixel)\
**Post date:** [March 8, 2019, 11:01am UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/15 "2019-03-08T11:01:53Z")

</div>

It turns out Polygon triangulation is quite a complex issue, and not at all trivial to implement when it comes to non-simple polygons (i.e. those intersecting themselves). I think this is out of scope for this library.

---

<div class="post-metadata">

**Author:** ![tadnicol](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/tadnicol/32/5141_2.png) [@tadnicol](https://forum.juce.com/u/tadnicol)\
**Post date:** [March 8, 2019, 8:58pm UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/16 "2019-03-08T20:58:54Z")

</div>

Gotcha, thanks for looking into it though. Much appreciated.

---

<div class="post-metadata">

**Author:** ![JussiNeuralDSP](https://avatars.discourse-cdn.com/v4/letter/j/c68b51/32.png) [@JussiNeuralDSP](https://forum.juce.com/u/JussiNeuralDSP)\
**Post date:** [March 12, 2019, 12:57pm UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/17 "2019-03-12T12:57:30Z")

</div>

I have use Javascript version of Clipper in my previous job. Worked great and could handle any geometry.

[http://www.angusj.com/delphi/clipper.php](http://www.angusj.com/delphi/clipper.php)

---

<div class="post-metadata">

**Author:** ![CrushedPixel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/crushedpixel/32/8654_2.png) [@CrushedPixel](https://forum.juce.com/u/CrushedPixel)\
**Post date:** [March 12, 2019, 3:55pm UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/18 "2019-03-12T15:55:11Z")

</div>

> [@JussiNeuralDSP](#):
>
> [angusj.com](http://www.angusj.com/delphi/clipper.php)

That looks like a very good library, thanks for the tip!

@tadnicol I believe you could just use this library in your project directly, and feed the points of the `juce::Path` you want to fill into it (using `juce::PathFlatteningIterator`). There’s nothing my library has left to do for that use-case 🙂

---

<div class="post-metadata">

**Author:** ![tadnicol](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/tadnicol/32/5141_2.png) [@tadnicol](https://forum.juce.com/u/tadnicol)\
**Post date:** [March 12, 2019, 4:25pm UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/19 "2019-03-12T16:25:03Z")

</div>

Thanks for the tip! I ended up just rolling my own using a super duper simple geometry shader. But for future tasks will definitely keep these libraries in mind 🙂

---

<div class="post-metadata">

**Author:** ![kunitoki](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/kunitoki/32/15_2.png) [@kunitoki](https://forum.juce.com/u/kunitoki)\
**Post date:** [October 12, 2020, 9:20am UTC](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405/20 "2020-10-12T09:20:54Z")

</div>

What is preventing this to be taken into account by the juce team?
