How to draw a line with width less than 1.0?

Hi,my teacher!
I want to draw lines with glLineWidth. But the default is 1.0. It’s too width for me. I want the width of lines to be 0.2. However the width of drawed lines looks like 1.0.
How can I draw lines with the width less than 1.0 such as 0.2.

Thanks

Hello,

well, I don’t think you can. glLineWidth is expressed in pixels; ie. how many pixels you want the cross-section of th eline to be.

If you want a width < 1.0 then you’re talking about a line that’s thinner than a pixel. Considering that pixels are point samples of light striking the camera, then you’ll need to factor in the other light also striking a line’s footprint. thus, you’d need to ~blend~ the line wiht the image. Try setting alpha to 0.2 and linewidth to 1.0 (ie. the line contributes 20% of the light to a given pixel, which you’d expect if the line is only 20% the width of the pixel).

cheers,
John

Increase resolution 5x in both x and y directions, I’d suggest 5120x3840. Don’t forget to buy a new monitor.

Another alternative: implement Bresenham’s line stuff in a software renderer and make it so that you only write 0.04 pixels each time.

In all seriousness, what do you expect? A pixel is a pixel is a pixel. There’s nothing you can do to display something smaller than a pixel - this also holds true when you apply anti-aliasing methods.

[This message has been edited by zeckensack (edited 03-20-2002).]

The simple answer would be to decrease the alpha of your line to whatever fraction of a pixel you want it to be. So, instead of trying to draw a line with 1/2-pixel width, just draw a one pixel wide line with 50% alpha.

That solution won’t actually be correct in an empirical sense, and it could require that you do depth-sorting where you weren’t before, but its basically what you are stuck with…

The simple answer would be to decrease the alpha of your line to whatever fraction of a pixel you want it to be. So, instead of trying to draw a line with 1/2-pixel width, just draw a one pixel wide line with 50% alpha.

isn’t that what i already said?

That solution won’t actually be correct in an empirical sense, and it could require that you do depth-sorting where you weren’t before, but its basically what you are stuck with…

but it IS correct. A pixel represents a samle of incoming light averaged over a particular region. Suppose you wanted your line to be 1/2 the width of a pixel, like so:

+--------+
|  ####  |
|  ####  |
|  ####  |
|  ####  |
+--------+

If you were to sample that pixel, then 50% of the time you’d get the line colour, and the other 50% of the time you’d get some colour behind it. so, the final pixel’s colour is (0.50)(line_colour) + (0.50)(bg_colour)… which is exactly the blend equation.

So, I’d argue that the approach is valid in an empirical sense: its explicitly stating what a ray-tracer will find, anyway, that 50% of the pixel’s colour is going to be from the line’s contribution.

cheers,
John

Another way to think about it. Suppose you wanted a line width 1/2 the size of a pixel for a xy image. Thats the same as drawing the line with a width of 1 pixel in an 2x * 2y image, and then downsampling the 2x * 2y image to xy. To down sample a given pixel in this case is the average of its neighbouring pixels, right? so you’re still blending the background colour with half the line colour (on average) and half the background colour.

cheers,
hjohn

I seem to remember something about anti-aliased lines need to be switch on for the card to do what you say automatically on lines thinner than 1.0.
There is a reason why the argument is a float.

You may still not be able draw lines < 1 pixel thick. You can use glGetFloatv (GL_LINE_WIDTH_RANGE , values ) to find the min and max width for anti-aliased lines. Mine happens to indicate 1.0 pixels is the minimum size (haven’t tested it though).

Most cards do actually have a line width range of [0.5 , 10000]. Check the hardware registry at delphi3d.net.

Not sure what the results looks like when drawing with glLineWidth of 0.5 though.

Originally posted by knackered:
I seem to remember something about anti-aliased lines need to be switch on for the card to do what you say automatically on lines thinner than 1.0.
There is a reason why the argument is a float.

But if you use integral values, antialiasing will still work fine. What is the difference between AA line of width = 1.5 and AA line of width 1.0 (or maybe ceiling function is used so I should say 2.0)?

I’ll check this out when I get home.

V-man

I agree that using alpha instead of less-than-one line thicknesses produces results that are what we expect, but I can’t escape a nagging suspicion that the “coverage” isn’t alway going to be correct.

Sure, if your line with width .1 passed through a pixel vertically or horizontally then it would cover 10% if the pixel’s area, but if your line went through a pixel diagonally from corner to corner, I don’t think that it would cover exactly 10% of the pixel’s area.

I don’t know whether the coverage will be correct or not, so I’ll change my position from “the result will not be correct” to “the result might not be correct.” It’s pretty easy to mentally “confirm” that it does the right thing, but its harder to be sure. I’ll admit that I’m not sure…

Besides, the effect always looks correct, so I probably shouldn’t worry…

What’s the point, people? The question was not ‘How do I display a semi-transparent line?’ or ‘How do fade the color of my lines into the background?’. The question was about displaying lines smaller that one pixel. Which can’t be done. And that’s the truth.

What’s the point, people? The question was not ‘How do I display a semi-transparent line?’ or ‘How do fade the color of my lines into the background?’. The question was about displaying lines smaller that one pixel. Which can’t be done. And that’s the truth.

you are mistaking alpha with transparency. Alpha is NOT synonymous with transparency, despite what it looks like when you start blending things. Alpha is a value representing the amount of coverage a point contributes to a pixel.. Yes, it is true transparent objects consequently have alpha < 1.0, but [/i] opaque objects can also have valid alphas of <1.0.[/i] So, saying alpha == transparency is not a valid statement.

A 2x2 window of pixels of an opaque object. the object fill is represented by #:

+----+---##
|    |  ###
|    | ####
+----+#####
|    ######
|   #######
+--########

the alpha values for this object’s footprint are:

0.0, 0.5
0.5, 1.0

respecrively. ie. the object does not touch the first pixel, covers half the second pixel, covers half of the third pixel, and completley covers all of the 4th pixel.

[b][i]Alpha does NOT represent transparency: it represents how much colour a given point contributes[i][b]

Thus, talking about alpha < 1.0 for a line is not saying that the line is transparent: all it is saying is that a line doesn’t completely fill a given pixel.

its not just a point of view, its a fundamental udnerstanding on what alpha represents.

Regardless of wording, alpha, pixel coverage, transparency, fancy anti-aliasing, whatever, will not allow you to actually display anything smaller than a pixel.

http://www.cs.adelaide.edu.au/~john/img1.jpg

Synthetic and Real examples:
http://www.cs.adelaide.edu.au/~john/img2.jpg

The synthetic example is a render from 3DS Max of diminishing cylinders. Note that when the footprint of the cylinder is less than a pixel that its affect on the image is a ~single~ line of pixels with increasing amounts of background colour (ie. as the cylinder gets smaller, its affect on the pixels colour is smaller, and thust the pixel assumes more of the background colour).

The real example is taken from some stoby poles outside my house. Note that the thick cables are very clearly defined, but the thinner cables (projecting to less than a pixel in the camera’s CCD) assume more of the sky colour because the sky contrinutes more light to the pixel than the cable.

Pixels are jsut samples. Of course you can capture things smaller than a pixel in an image. think about it… an atom is smaller than a pixel. if an antom can’t be seen, then all cameras would ever do is take black pictures. (An elephant is composed of an insanely large number of things, all of which are smaller than the CCD of a camera. yet, we can see the elephant in the image because each photon reflected from each atom is contributing a tiny amount of light to the ~final~ colour of the pixel).

Saying “it is impossible, and thats’ just final” isn’t an argument. I assert that the sky is green. that doesn’t mean i’m right, tho’.

1 Like

Originally posted by john:
Note that when the footprint of the cylinder is less than a pixel that its affect on the image is a ~single~ line of pixels with increasing amounts of background colour (ie. as the cylinder gets smaller, its affect on the pixels colour is smaller, and thust the pixel assumes more of the background colour).[/b]

That’s exactly what I wanted to point out. You get an image of a line that’s one pixel wide. You fade it into the background according to its coverage value, but it’s still one pixel wide. I know what you wanted to say, and I must apologize for getting you upset. I was riding on the ‘width of visible output’ issue while you were already providing solutions for a visually acceptable workaround.

Hey, I wasn’t upset. I just really love techno arguments, sometimes :stuck_out_tongue:

I erroneously thought you were one of those guys that think alpha == transparency and pixel == little square.

But, hey! its all good :slight_smile:

cheers,
john

Well,
In an absolute way you can draw lines with a 0.2 width … but you must draw antialiased lines and it depends on your configuration :
On my SUn/solaris I have this width range : [0.5 - 100] on my PC/linux/quadro2 this one [1-10]

You can get your range with this function :
glGetFloatv(GL_LINE_WIDTH_RANGE , param);

where param is a GLfloat array

You can get lines of width 0.5 on NVIDIA HW, or up to 10. Query the smooth line width range and granularity. The granularity will be 0.125. Note that aliased lines can only be integral sizes.

Having wide line support is clearly nice when you want to draw a wireframe model at varying window sizes, and for the model to look the same (just higher quality) at larger window sizes. Otherwise the lines effectively get thinner.

  • Matt