Simple question: I want to draw lines with rounded joints in OpenGL. Something like this:
{"name":"lines.png Example","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/3\/93de19c9d286247f057bc07150f06724.png","w":256,"h":256,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/3\/93de19c9d286247f057bc07150f06724"}
Is there an easy way to do this? Or will I have to resort to hacky black magic?
I've seen this done before in OpenGL, well it was a very cool "oil paint" filter technique but it used rounded lines. I'm not entirely sure how you can do this, but if you can make your lines rounded at the ends, joining two will give you a rounded look. If you make the lines from bitmaps then it should be very easy to pull off.
A circle where the two meet?
A circle where the two meet?
That was my first thought as well. Unfortunately, I think I will require blended lines at some point.
That was my first thought as well. Unfortunately, I think I will require blended lines at some point.
In that case you could use the stencil buffer. Just draw a mask of the line, then use that to draw the actual blended line. I'm not too sure about speed but it should work.
glEnable(GL_LINE_SMOOTH);?
In that case you could use the stencil buffer. Just draw a mask of the line, then use that to draw the actual blended line. I'm not too sure about speed but it should work.
Neat idea, thanks! Of course, the stencil buffer is black magic to me, but I guess I had to learn how to use it at some point in my life...
glEnable(GL_LINE_SMOOTH);?
Unfortunately, that only enables antialiasing...
Unfortunately, the stencil buffer can't be used the same way an alpha mask can, so you lose antialiasing on your lines. Though that might not be a problem.
Alternatively, if that lines are not all that dynamic, you could render the line (together with circles at the joints) to a GL_ALPHA texture, and then use that texture with a quad to render it.
Unfortunately, the stencil buffer can't be used the same way an alpha mask can, so you lose antialiasing on your lines. Though that might not be a problem.
Huh? You get a stencil value per sample, so you can stencil test per sample. Stencil and AA work just fine together.
Note that GL_LINE_SMOOTH has little to do with anti-aliasing.
Note that GL_LINE_SMOOTH has little to do with anti-aliasing.
Huh?
Antialiasing is controlled with Enable and Disable using the symbolic constant LINE SMOOTH.
well, heres my "solution"
since you would really only notice the curved joints on rather thick lines, and since modern graphics cards dont draw lines, but rather 2 (i think 2 maybe more) thin long triangles to make a line, i would suggest you make your lines with 2 triangles each and have a triangle fan where they meet. (the inside corners of the lines would touch, and the open space at the top would be filled with the triangle fan)
perhaps not the best solution, but it would almost certainly be faster than the stencil buffer.
I think a single textured quad would be faster, not that it matters too much.
What Jakub suggested sounds good. Draw the line with Gimp or something at high resolution, 512x512 maybe; Load it into your program, and then use a function that can transform it to match certain parameters. Scale and rotation is all that's need for it to draw the line from any point A to point B.
Huh? You get a stencil value per sample, so you can stencil test per sample. Stencil and AA work just fine together.
Okay, which of the following assumptions is wrong?
- to use the stencil buffer to render the lines later, one would need to "render" the quads and the circle at the joint to the stencil buffer
- the stencil buffer can hold a number of bitplanes, so the above rendering will produce only a bitmask in one/several of those, not an actual transparency mask
- the actual rendering is done using a quad or some other object covering the whole area the line covered. Some parts are stenciled out with GL_STENCIL_TEST, which can only decide IF a pixel is drawn or not, so basically this would correspond to an alpha of 1.0 or 0.0
- so, if we do use it that way, we only have pixels that are 100% the color of the quad or 100% the color of what was there before
- so, the line will be jagged and not smooth, hence the phrase "you will lose the antialiasing"
The implied assumption that one stencil buffer pixel = one screen pixel is wrong. As with every other buffer on any card with full scene aa turned on, the stencil buffer is running at some resolution much greater than your screen such that super/subsampling (whichever marketing term you subscribe to) can properly achieve anti-aliasing.
The key part of Bob's post was "Note that GL_LINE_SMOOTH has little to do with anti-aliasing", explaining what sort of anti-aliasing he was talking about!
To be honest though, I think I must not really be following the conversation. Why has stencilling come up? With or without the main problem gnolam wants to address is how to communicate that outline to the graphics card.
Huh?
I believe this is a very liberal use of the term "antialising" in the specification. Notice how the enumerant is called "LINE_SMOOTH" and not "ANTIALIASED_LINE". If you also actually read the spec, you will see that line smoothing has little to do with aliasing:
Rasterized antialiased line segments produce fragments whose fragment squares
intersect a rectangle centered on the line segment. Two of the edges are parallel to
the specified line segment; each is at a distance of one-half the current width from
that segment: one above the segment and one below it. The other two edges pass
through the line endpoints and are perpendicular to the direction of the specified
line segment.
The line isn't sampled at a higher frequency (which is what antialising entails), but rather is smoothed out by drawing additional lines!
since modern graphics cards dont draw lines, but rather 2 (i think 2 maybe more) thin long triangles to make a line
Some hardware manufacturers may have gone down to drawing lines this way, but pretty much all Nvidia GPUs that I know of render lines as lines, not triangles.
Rendering lines as triangles has a whole lot of issues associated with it, and in no way can correctly implemenent either OpenGL or Direct3D specifications.
Okay, which of the following assumptions is wrong?
All of them are right, except for the last two:
- so, if we do use it that way, we only have pixels that are 100% the color of the quad or 100% the color of what was there before
- so, the line will be jagged and not smooth, hence the phrase "you will lose the antialiasing"
Ahh, but now you are confusing samples with pixels! There are typically N samples per pixels (where N is 1 to 8 these days), so you can actually get up to 8 different values when downsampling samples to pixels, if samples are only allowed to contain two different values.
Nothing stops you from using line smothing, stenciling and multisampling together (although line smothing in combination with multisampling doesn't always give you the result you expect).
Man after thinking about it the simplest way is to use quads + triangle fans, you could probably compute all of that relatively quickly, and rendering would be really fast with all the anti-aliasing you will want.
To be honest though, I think I must not really be following the conversation. Why has stencilling come up? With or without the main problem gnolam wants to address is how to communicate that outline to the graphics card.
As I understand it, the stencil method will allow me to use the extremely simple line/circle (line/point?) approach, but still get whatever blending I wanted.
(To be honest, i don't know anything about programming OpenGL, but i think the following observation is independet of that fact. Maybe i'm wrong and all that talk above about "stencil buffers"? already adresses that problem.)
Where would you want to place the circle and how large should it be?
(here's a pic to illustrate the problem i see in that approach)
http://homepages.compuserve.de/DennisTapier/allegroforum/linesmootherror.png
Dennis: Second method, just make the lines shorter - meet at the center of the circle, rather than making the lines perpendicular.
Bob:
Thanks, I stand corrected. While you can't use the nice-and-easy way GL_LINE_SMOOTH gives you, it is still possible to make them smooth, but you have to use proper multisampling.
Dennis:
I think the first would be the best, with clipping set to eliminate the protruding part.
I think the first would be the best, with clipping set to eliminate the protruding part.
What's wrong with my suggestion?
All he has to do is draw 2 lines to meet at single point which should leave a space (should be a square at the top) - then he can draw a circle in the meeting point with the same diameter to connect the corners of the 2 lines. And it'd work even if the lines change angle.
Archon:
I think i got it.:) pic:
http://homepages.compuserve.de/DennisTapier/allegroforum/linesmoothcorrect.png
(the circle of course needs to be filled and the white lines are only there to show that the black lines need to be understood as rotated rectangles)
Jakub:
Archon's method seems easier, because it does not involve any clipping.
The line isn't sampled at a higher frequency (which is what antialising entails), but rather is smoothed out by drawing additional lines!
Isn't your definition of anti-aliasing too specific? I would think that anything which removes the effects of aliasing is a method of antialiasing.
Dennis: I can only defend my choice on the grounds of "looking better", which is mainly personal preference. In your example the difference in looks wouldn't be that much, but please look at the attached image.
The left line shows my approach (not exactly your #1, but closer to that than to #2) - the center of the circle is depicted in orange, the clipping plane is blue with green normal, the red lines show the rectangle limits.
Of course, one can choose any point between the inner and outer corner of the non-rounded intersection, and make this the center of the circle. This allows for different degrees of roundness - my approach being "100%", yours being "50%".
Hm, the more I think about it, the more arguments I find for using your approach. One especially prominent is that your line is actually the shape that would be swept by a circular brush with the diameter corresponding to the line width.
Okay, you win .
By the way, I'm wondering if gnolam actually implemented this .
[EDIT: Corrected some things.]
Okay, you win .
Cookies to Archon, it was his idea;). With "I think i got it.", i meant "i understood(==got) it".
By the way, I'm wondering if gnolam actually implemented this .
Me too, as i said, i have no idea about OpenGL programming. I was just interested in the 'visual anomalies', which i first thought the "line, circle" approach could cause, but thanks to Archon that problem is solved.