Funny timing on this post, I just finished implementing this a couple days ago for a little effect in a game. I followed the math in this comment that is now only viewable from the archive http://web.archive.org/web/20190614093605/https://forum.libc...
I notice you use 4 triangles per segment but I believe it's always possible to use only 2 if you only have miter and bevel caps.
For miter caps, you need 2, for bevel caps, you need 3.
But it is actually way more complicated than that in the general case. Notice how there is some overlap, not very pretty with transparency. There are ways around this problem, for example using a stencil buffer, but if you don't want that either and instead go a proper triangulation, this becomes quite involved.
The problem is when segments are shorter than the inner intersection point. In the example in the article, that's when I1 is outside of [A1, A1'] or [B1, B1']. Doing it properly would require taking the geometry of the entire figure into account, you can't just draw it segment by segment and fix the joints.
For example, if you draw a closed polygon that is smaller than the line thickness, all internal geometry will disappear so you have to triangulate the shape using only the outer vertices. How to calculate that looks like an interesting problem that would need a much longer blog post...
Yes, this problem seems intuitively not so hard -- but without flattening first to a pixel buffer, it is a formidable challenge.
You can use 2 triangles with miter join, I've started with this approach, but the bevel join creates (in general) a pentagon, thus this should be doable with 3 triangles I suppose.
I used something close to this to implement a whiteboard marker with texture and transparency. If your browser supports WebGL, feel free to try https://limnu.com/d/new.html (BTW It’s a multi-player whiteboard you can share & collab.) Is that a shameless plug? I’m not involved anymore and won’t make any money, but I’m proud of the implementation, and happy if the current stewards of the site get some traffic or business.
Aside from that, for the sake of discussion and playing devil’s advocate I’ll take a small pedantic issue with the very first sentence. There are multiple ways to do this kind of thing without triangulating. (And I’m currently working on making one available publicly.) Clever shaders are one way to render lines without triangles. Ray tracing is another. Triangles are useful and easy and have broad support, so they make sense, but they aren’t the only option.
Aw, I looking forward to seeing the author's implementation for the other two cap types, but it was a nice read regardless. These types of links - right between general interest and too niche for most readers to care - are why HN is such a great site.
Doing something pretty similar with u,v coordinates to project half-edge arrows onto triangle faces.
ah, bitter sweet memories. a very long time ago I was working on a hw accelerated 2D api, and spent some time on this problem.
ok, how compiling this? Why can wrote Makefile?
See jv_polyline_premake5.lua, I'd prefer a Makefile myself, but everyone has their own preference on build systems ...