Hi,
I managed to come up with a solution of my own. It's basically a 2D version of the shader found by Ben, but with different characteristics for the miter (explained below).
Construction of the line starts with a segment:
P0 and P1 are Vec2f's. The line is defined by Vec2f line = p1 - p0
and the normal (n) is defined by Vec2f normal = Vec2f( -line.y, line.x).normalized().
You could then draw the segment by multiplying the normal by the thickness and add or subtract it from the end points:
Vec2f a = p0 - thickness * normal;
Vec2f b = p0 + thickness * normal;
Vec2f c = p1 - thickness * normal;
Vec2f d = p1 + thickness * normal;
But when two segments are joined, we need to calculate the cross-section of the joint to form the miter:
First, I calculate the tangent (t) as follows:
Vec2f tangent = ( (p2-p1).normalized() + (p1-p0).normalized() ).normalized()
Next, I find the miter line (m), which is the normal of the tangent:
Vec2f miter = Vec2f( -tangent.y, tangent.x )
The correct length (d) of the miter can then be found by projecting it on one of the normals (shown in red) using the dotproduct. This gives us a value that is the inverse of the desired length, so:
float length = thickness / miter.dot( normal )
That's all the information we need. Now we can construct the triangle mesh:
The result is quite nice, even for sharp angles:
Note that this algorithm does not always give the desired result at very sharp angles or if the line segment is too short. This can be detected and taken care of, for example by converting the sharp angle to a blunt one by adding an extra point.
You can play with the algorithm in this sample:
It can also be found on GitHub:
I haven't written the TriMesh code yet, and expect some difficulties with texturing (all triangles have different sizes, requiring perspective correction). But I am hopeful I can soon draw awesome 2D textured lines :) Thanks everyone for helping me out.
-Paul