Discussion:
Losing row and coloumn 0 when switching to Ortho mode.
(too old to reply)
R.Wieser
2015-09-09 15:16:03 UTC
Permalink
Hello All,

I'm switching to Ortho mode pretty-much the standard way: from setting the
viewport thru setting the projection-matrix mode, setting identity, calling
glOrtho, switching back to model-matrix mode and setting identity here too
(only difference, I've defined it vertically upside-down, placing the origin
in the upper-left).

For the arguments for both of the above I used 0,0 and the with and height
returned by the WM_SIZE event.

After that I did draw a 2D rectangle using a lineloop, with its corners at
0,0 and 128,128.

** The problem is that the top and left lines of that square lineloop are
not visible, where I think they should be. What is going on here ?

When I draw the same rectangle starting from 1,1 I do see the upper and left
sides, but they are then laying directly against the inner sides of the
control (the OpenGL canvas is displayed in).

Regards,
Rudy Wieser
Jean-Christophe
2015-09-09 18:01:42 UTC
Permalink
Post by R.Wieser
Hello All,
I'm switching to Ortho mode pretty-much the standard way: from setting the
viewport thru setting the projection-matrix mode, setting identity, calling
glOrtho, switching back to model-matrix mode and setting identity here too
(only difference, I've defined it vertically upside-down, placing the origin
in the upper-left).
For the arguments for both of the above I used 0,0 and the with and height
returned by the WM_SIZE event.
After that I did draw a 2D rectangle using a lineloop, with its corners at
0,0 and 128,128.
** The problem is that the top and left lines of that square lineloop are
not visible, where I think they should be. What is going on here ?
When I draw the same rectangle starting from 1,1 I do see the upper and left
sides, but they are then laying directly against the inner sides of the
control (the OpenGL canvas is displayed in).
Regards,
Rudy Wieser
Rudy, if this can help you, the following code displays
a rectangle with border and partially transparent bgnd
( image below, located at the top left of the screen )
Loading Image...

I didn't try to draw the border _after_ drawing the bgnd,
anyway note the 'y1+1' and the 'x2-1' bgnd here ...

void fctDisplayRectBgnd( int x1, int y1, int x2, int y2 )
{
glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); // border = white
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glRecti( x1, y1, x2, y2 ); // border
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glColor4f( 0.3f, 0.3f, 0.3f, 0.5f ); // gray-ish bgnd, 0.5 = trensparency
glRecti( x1, y1+1, x2-1, y2 ); // background
glDisable(GL_BLEND);
}

// HTH
R.Wieser
2015-09-10 09:48:05 UTC
Permalink
Jean-Christophe,
Post by Jean-Christophe
Rudy, if this can help you, the following code displays
a rectangle with border and partially transparent bgnd
Thanks, but that code and image does not show the problem: Have you ever
tried to use 0,0 for those "x1" and "y1" arguments ? If you did, did you
still see the upper and left border lines ? (or lower and left if you
didn't invert the vertical axis like I did)

And try this: Draw a line between x,y and x+1, y+100. The line will need to
"step over" to the next horizontal pixel somewhere. If you do not see a
line with that "step over" halfway down the line you've got the same problem
I described.

Also, I've got a problem with the coordinates of the transparent rectangle:
its "x1" and "y2" are the same as when you draw the boundary, meaning it
*should* overlap at least two of those border lines. The odd thing is,
your image does not show such overlapping ...

Regards,
Rudy Wieser
Post by Jean-Christophe
Post by R.Wieser
Hello All,
I'm switching to Ortho mode pretty-much the standard way: from setting the
viewport thru setting the projection-matrix mode, setting identity, calling
glOrtho, switching back to model-matrix mode and setting identity here too
(only difference, I've defined it vertically upside-down, placing the origin
in the upper-left).
For the arguments for both of the above I used 0,0 and the with and height
returned by the WM_SIZE event.
After that I did draw a 2D rectangle using a lineloop, with its corners at
0,0 and 128,128.
** The problem is that the top and left lines of that square lineloop are
not visible, where I think they should be. What is going on here ?
When I draw the same rectangle starting from 1,1 I do see the upper and left
sides, but they are then laying directly against the inner sides of the
control (the OpenGL canvas is displayed in).
Regards,
Rudy Wieser
Rudy, if this can help you, the following code displays
a rectangle with border and partially transparent bgnd
( image below, located at the top left of the screen )
http://www.cjoint.com/data/EIiqQXEYaTh_0.jpg
I didn't try to draw the border _after_ drawing the bgnd,
anyway note the 'y1+1' and the 'x2-1' bgnd here ...
void fctDisplayRectBgnd( int x1, int y1, int x2, int y2 )
{
glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); // border = white
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glRecti( x1, y1, x2, y2 ); // border
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glColor4f( 0.3f, 0.3f, 0.3f, 0.5f ); // gray-ish bgnd, 0.5 = trensparency
glRecti( x1, y1+1, x2-1, y2 ); // background
glDisable(GL_BLEND);
}
// HTH
Jean-Christophe
2015-09-10 18:18:09 UTC
Permalink
Rudy,
Post by R.Wieser
Thanks, but that code and image does not show the problem
Well then, there's no problem anymore, is it ? :-)
Post by R.Wieser
Have you ever tried to use 0,0 for those "x1" and "y1" arguments ?
If you did, did you still see the upper and left border lines ?
(or lower and left if you didn't invert the vertical axis like I did)
Well, thank you for asking me to do it for you.
x1=0 will cause the left vertical line to disappear, while
y1=0 will NOT cause the upper horizontal line to disappear,
and of course the two other lines stays the same as before.

Since I can put the whole box and its text at any given (x,y)
position anywhere on the screen, I've got what I wanted,
n'I like to let some pixels around things to let them 'breathe'.
Post by R.Wieser
(snip)
its "x1" and "y2" are the same as when you draw the boundary, meaning it
*should* overlap at least two of those border lines. The odd thing is,
your image does not show such overlapping ...
Yes, and I tried several different 'side-effect' values to check it out,
while setting the backgroud to 'totally opaque' to be able to see
if it overlaps the border or not.

For the border rectangle drawn by glRecti( x1, y1, x2, y2 )
the drawing actually starts at x1 and ends at y2.

For the bgdn rectangle drawn by glRecti( x1, y1+1, x2-1, y2 )
the drawing actually starts at x1+1 and ends at y2-1.

Anyway you can reverse order : draw bgnd first, then the border.

Cheers
R.Wieser
2015-09-10 19:45:38 UTC
Permalink
Jean-Christophe,
Post by Jean-Christophe
Well then, there's no problem anymore, is it ? :-)
Well, thats one way to deal with them. :-)
Post by Jean-Christophe
Well, thank you for asking me to do it for you.
That was not my intention. I know what the result is on my machine, but
thought you might like the be made aware of possibly the same problem on
yours.

On the other hand, if you would see the same I did than that would be a
signal its not just some stupid mistake I made somewhere.

Hmm. Maybe that suggestion was a mix of a little bit for you, and a little
bit for me ...
Post by Jean-Christophe
x1=0 will cause the left vertical line to disappear,
Ok, so you're loosing the Zero column too.
Post by Jean-Christophe
while y1=0 will NOT cause the upper horizontal line to disappear,
and of course the two other lines stays the same as before.
Hmmm ....
Post by Jean-Christophe
Since I can put the whole box and its text at any given (x,y)
position anywhere on the screen, I've got what I wanted,
I wanted to go a bit further by adding clipping to the textbox, which
subsequently caused me all this trouble. :-|
Post by Jean-Christophe
For the border rectangle drawn by glRecti( x1, y1, x2, y2 )
the drawing actually starts at x1 and ends at y2.
For the bgdn rectangle drawn by glRecti( x1, y1+1, x2-1, y2 )
the drawing actually starts at x1+1 and ends at y2-1.
Yeah, I noticed that too, and didn't think that was intended or correct.


A bit more google-fu lead me to whats probably the answer to that: OpenGL
tries to draw, in Ortho mode, its pixels *between* the pixels of the screen.

The reason that those lines disappear (on my both left and top, on yours
only the left) is that the smallest negative rounding error makes the line
that is supposed to be on X or Y of Zero (but inside OpenGL actualy on 0.5)
to be rounded to Zero, and thus disappear.

Its also the reason that vertical line test I mentioned in my previous post
here appeared as a straight line: it was actually drawn from x-0.5, y-0.5 to
x+1-0.5, y+100-0.5 . And with rounding applied that causes X not to change
(but for at its very start or end).

Someone posted setting a translation of 0.5, 0.5 (, 0.0) as a solution, but
that will most likely interfere with everything else too.

My own solution is a bit cruder(?), but still does give good results (the
rectangle and the border now do again align using the same coordinates): I
did set the line width to 2.0 (meaning it will, on a vertical line, draw a
pixel left and right of the "OpenGL position" of it being in between both).

In short, It looks like my problem started because I was simply not aware of
OpenGLs method of defining its pixel positions as being on the intersections
of the screen-pixel grid instead of in the gridboxes themselves (where the
screen/videocard places them).

Or even shorter: Novice problems. :-)

Regards,
Rudy Wieser
Post by Jean-Christophe
Rudy,
Post by R.Wieser
Thanks, but that code and image does not show the problem
Well then, there's no problem anymore, is it ? :-)
Post by R.Wieser
Have you ever tried to use 0,0 for those "x1" and "y1" arguments ?
If you did, did you still see the upper and left border lines ?
(or lower and left if you didn't invert the vertical axis like I did)
Well, thank you for asking me to do it for you.
x1=0 will cause the left vertical line to disappear, while
y1=0 will NOT cause the upper horizontal line to disappear,
and of course the two other lines stays the same as before.
Since I can put the whole box and its text at any given (x,y)
position anywhere on the screen, I've got what I wanted,
n'I like to let some pixels around things to let them 'breathe'.
Post by R.Wieser
(snip)
its "x1" and "y2" are the same as when you draw the boundary, meaning it
*should* overlap at least two of those border lines. The odd thing is,
your image does not show such overlapping ...
Yes, and I tried several different 'side-effect' values to check it out,
while setting the backgroud to 'totally opaque' to be able to see
if it overlaps the border or not.
For the border rectangle drawn by glRecti( x1, y1, x2, y2 )
the drawing actually starts at x1 and ends at y2.
For the bgdn rectangle drawn by glRecti( x1, y1+1, x2-1, y2 )
the drawing actually starts at x1+1 and ends at y2-1.
Anyway you can reverse order : draw bgnd first, then the border.
Cheers
Nobody
2015-09-11 02:57:01 UTC
Permalink
Post by R.Wieser
A bit more google-fu lead me to whats probably the answer to that: OpenGL
tries to draw, in Ortho mode, its pixels *between* the pixels of the screen.
A projection matrix has nothing to do with pixels. It transforms
between coordinate systems. The matrices generated by glOrtho and
gluOrtho2D map the given rectangle to the bounds of the unit cube in
normalised device coordinates, which are in turn mapped by the viewport
transformation to the bounds of the viewport (note: *bounds*, not to the
centres of the boundary rows and columns of fragments).
Post by R.Wieser
In short, It looks like my problem started because I was simply not aware
of OpenGLs method of defining its pixel positions as being on the
intersections of the screen-pixel grid instead of in the gridboxes
themselves (where the screen/videocard places them).
You appear to have it backwards.

A fragment (pixel) doesn't have a specific position. It's not a point,
it's a rectangle. Its corners have specific positions, as does its centre.

E.g., the lower-left corner of the fragment at the lower-left corner of
the window is <0,0> in window coordinates. The upper-left corner of
that fragment is <1,1>, and its centre is <1/2,1/2>. For any fragment, the
window coordinates of its corners will be integers, the window coordinates
of its centre will be <x+1/2,y+1/2> where x and y are integers.

When rasterising a line of width 1 without anti-alisasing, the fragments
which are affected are those where the line passes through an inscribed
diamond, i.e. the line must pass within a distance of half a fragment from
the fragment's centre according to the Manhattan (aka taxicab) metric.
Figure 14.2 in section 14.5.1 of the OpenGL 4.5 specification makes this
clear (the same figure exists in other versions, but the section numbers
vary).

If you rasterise a horizontal or vertical line whose endpoint coordinates
are integers in window coordinates, the line will run exactly along the
boundary between two rows or columns of fragments, and thus be exactly
half a fragment from the centres of the fragments on either side. The
result is that the choice of exactly which row or column of fragments is
rasterised will be affected by even the smallest rounding error.
R.Wieser
2015-09-12 12:36:08 UTC
Permalink
Nobody,
Post by Nobody
A projection matrix has nothing to do with pixels.
I did not say that. That I even mentioned a projection mode was to give
anyone a chance to do the same thing I did, and (likely) see the same
results.
Post by Nobody
You appear to have it backwards.
I don't think so, but even if is, does that matter ? The end result of my
train of thought is the same you describe. And as long as there is nothing
conflicting* with my explanation its as good as any.

*please tell me if you see any. Although I do not just go along your POV,
I'd like to keep the/my explanation consistent.
Post by Nobody
If you rasterise a horizontal or vertical line whose endpoint
[snip]

Yep. Thats what I tried to and, IIRC, even did say somewhere.

All-in-all, you're using a lot more words to say what I already did: the
reason OpenGLs pixels sometimes* do not get placed where you think they
should be is because of a non-alignment of OpenGLs and the physical
screen-pixel grid. That non-alignment might be good for a 3D projection,
but obviously not when using Ortho. So why is it still done that way ?

*One "fun" thing I observed was when I, in ortho mode, did draw a line loop
and than a quad ontop of it using the same integer coordinates. Two
line-loop sides peeped out from under the quad. And pardon me, but that
should *not* have happened.

And by the way, I did try to align those virtual and screen pixel grids by
shifting the ortho projection half a pixel both horizontally and vertically.
The end result was underwhelming ... :-\

The only "solution" I can think of is to give a odd-width line a different
treatment than a quad, thereby aliviating differences between the line and
the quad screen results. But I would thouroughly dislike that, as it would
be nothing more than a clumsy hack.

By the way, I simply did change the line-width to an even value. Now a
drawn line from x,y to x+1,y+100 again has that little 'knick' halfway down.
:-) Yeah, its not a perfect solution, but its way better than most of the
others.

I'll look into anti-alisassing though.

Regards,
Rudy Wieser
Post by Nobody
Post by R.Wieser
A bit more google-fu lead me to whats probably the answer to that: OpenGL
tries to draw, in Ortho mode, its pixels *between* the pixels of the screen.
A projection matrix has nothing to do with pixels. It transforms
between coordinate systems. The matrices generated by glOrtho and
gluOrtho2D map the given rectangle to the bounds of the unit cube in
normalised device coordinates, which are in turn mapped by the viewport
transformation to the bounds of the viewport (note: *bounds*, not to the
centres of the boundary rows and columns of fragments).
Post by R.Wieser
In short, It looks like my problem started because I was simply not aware
of OpenGLs method of defining its pixel positions as being on the
intersections of the screen-pixel grid instead of in the gridboxes
themselves (where the screen/videocard places them).
You appear to have it backwards.
A fragment (pixel) doesn't have a specific position. It's not a point,
it's a rectangle. Its corners have specific positions, as does its centre.
E.g., the lower-left corner of the fragment at the lower-left corner of
the window is <0,0> in window coordinates. The upper-left corner of
that fragment is <1,1>, and its centre is <1/2,1/2>. For any fragment, the
window coordinates of its corners will be integers, the window coordinates
of its centre will be <x+1/2,y+1/2> where x and y are integers.
When rasterising a line of width 1 without anti-alisasing, the fragments
which are affected are those where the line passes through an inscribed
diamond, i.e. the line must pass within a distance of half a fragment from
the fragment's centre according to the Manhattan (aka taxicab) metric.
Figure 14.2 in section 14.5.1 of the OpenGL 4.5 specification makes this
clear (the same figure exists in other versions, but the section numbers
vary).
If you rasterise a horizontal or vertical line whose endpoint coordinates
are integers in window coordinates, the line will run exactly along the
boundary between two rows or columns of fragments, and thus be exactly
half a fragment from the centres of the fragments on either side. The
result is that the choice of exactly which row or column of fragments is
rasterised will be affected by even the smallest rounding error.
Nobody
2015-09-13 06:17:35 UTC
Permalink
Post by R.Wieser
All-in-all, you're using a lot more words to say what I already did: the
reason OpenGLs pixels sometimes* do not get placed where you think they
should be is because of a non-alignment of OpenGLs and the physical
screen-pixel grid. That non-alignment might be good for a 3D projection,
but obviously not when using Ortho. So why is it still done that way ?
The issue isn't non-alignment, but alignment. And it isn't ortho versus
perspective, it's an issue of the specific case of trying to draw
untransformed, orthogonal single pixel lines versus ... pretty much
everything else.

It works how it does because it makes sense. The fact that drawing
single-pixel orthogonal lines means that you have to think about
what you're actually doing doesn't detract from that.

Fudging the math to make that particular case easier would only make sense
if that particular case was common, and it isn't. It only applies if the
primitives being rendered are being positioned based upon the screen's
pixel grid, and the overall combination of the model-view, projection and
viewport transformations happens to be an identity transformation. Which
is rarely the case.
Post by R.Wieser
*One "fun" thing I observed was when I, in ortho mode, did draw a line
loop and than a quad ontop of it using the same integer coordinates. Two
line-loop sides peeped out from under the quad. And pardon me, but that
should *not* have happened.
That's like saying a coin toss which landed on tails "should have" landed
on heads.

For a filled primitive, having the edges lie exactly mid-way between two
rows of pixels is the ideal case, because it's clear-cut which pixels are
inside and which pixels are outside. For a line, it's the worst possible
case, as each set of pixels has exactly the same strength of claim to
being on the line.

For typical OpenGL usage, this isn't a problem. By the time that the 3D
coordinates have been subjected to the model-view and projection
transformations, projective division, and the viewport transformation, the
chances of the resulting line being exactly betwen two rows of pixels are
negligible. That situation only happens when you go out of your way
to create it.
Post by R.Wieser
The only "solution" I can think of is to give a odd-width line a different
treatment than a quad, thereby aliviating differences between the line and
the quad screen results. But I would thouroughly dislike that, as it
would be nothing more than a clumsy hack.
Which is why OpenGL doesn't try to do it. Being predictable, consistent
and rational are more important than being "intuitive".

And as time goes on, this issue will become progressively less relevant.
Even at 1920x1080 (which is about the lowest-resolution monitor you can
buy nowadays), single-pixel lines are barely visible. This is a
significant problem for legacy software which works in pixel coordinates
rather than e.g. a fraction of the window size. And as "4K" displays
(4096x2160 or 3840x2160) get cheaper, they'll start becoming the de facto
standard for PC monitors.
R.Wieser
2015-09-14 10:51:51 UTC
Permalink
Nobody,
Post by Nobody
The issue isn't non-alignment, but alignment.
Que ? Isn't not having the first the latter, and vice verse ? Whats your
distinction between the two ?

But if you want to make a point of it (pun not intended), I would certainly
call it an issue of *non* alignment: I work with what I see (whats displayed
on my screen), and the method used behind the scenes (sorry, pun not
intended here either :-) ) isn't relevant to me, as long as it gives me the
correct results.
Post by Nobody
And it isn't ortho versus perspective
Ehrmm... I can't remember I ever said that, or even where I suggested
anything like it ...

... and this is the second time I have said that.
Post by Nobody
it's an issue of the specific case of trying to draw untransformed,
orthogonal single pixel lines versus ... pretty much everything else.
Nope. Although its easier to ignore in a 3D environment (which is often
quite dynamic, and therefore such an error, if-and-when it appears, is gone
before you notice it), it most likely has got the very same problem.
Post by Nobody
It works how it does because it makes sense.
Nope, it doesn't make sense *at all*. I've already given you two examples
showing the problems with it, so I have absolutily no idea why you say it
does. Care to explain (and why you ignore them) ?
Post by Nobody
Fudging the math .... Which is rarely the case.
Only *every time* someone wants to overlay his 3D scene with some 2D info,
which I imagine is quite often. In other words, I can't agree with you here
either. Sorry.
Post by Nobody
That's like saying a coin toss which landed on tails "should have"
landed on heads.
I'm sorry, you completely lost me here. You seem to say that, when using
the same coordinates for both a filled and an open rectangle the chance they
will actually overlap will be very, *very* small ?

In that case the used math/method/implementation is not worth its salt, if
any. :-(
Post by Nobody
For typical OpenGL usage, this isn't a problem.
...
Post by Nobody
That situation only happens when you go out of your way
to create it.
Absolutily. Setting up a basic Ortho projection and than trying to draw a
simple rectangle on it with a differently colored border is ofcourse "going
outof my way". </sarcasm>
Post by Nobody
Which is why OpenGL doesn't try to do it. Being predictable,
consistent and rational are more important than being "intuitive".
Lol. The ony "predictable, consistent and rational" about it is that the
tiniest rounding error can cause the intended pixel to jump from one to the
next screen position.

The only thing you are telling me here is that you do not mind problems, as
long as you know about it and its consistent.

I personally rather have something "predictable, consistent and rational"
that does not include 'magic behaviour' and as such also is "intuitive".
Post by Nobody
And as time goes on, this issue will become progressively less
relevant. Even at 1920x1080 (which is about the lowest-
resolution monitor you can buy nowadays), single-pixel lines
are barely visible.
Ah, the old "problem solving" by obsfucation: If you do not see it its not
there. Sorry, but I've been "at it" long enough to know that that kind of
"solutions" will often come back with a vengeance.


Bottom line: I've (still) not seen you give any explanation to why placing
the virtual pixels at the most awkward of places in regard to the physical
ones is a good idea. I therefore have absolutily no idea why you are
definding it.

And neither have I seen any suggestion to solve the problems caused by it
.... :-(

Regards,
Rudy Wieser

P.s.
Ortho projection seems to be a bit of a stepchild: Even drawing simple text
on it in a "predictable, consistent and rational" way is an exercise in
frustration. One font (bitmap) does not honour viewports, another one (3D)
gets distorted. Neither is therefore usefull.
Post by Nobody
Post by R.Wieser
All-in-all, you're using a lot more words to say what I already did: the
reason OpenGLs pixels sometimes* do not get placed where you think they
should be is because of a non-alignment of OpenGLs and the physical
screen-pixel grid. That non-alignment might be good for a 3D projection,
but obviously not when using Ortho. So why is it still done that way ?
The issue isn't non-alignment, but alignment. And it isn't ortho versus
perspective, it's an issue of the specific case of trying to draw
untransformed, orthogonal single pixel lines versus ... pretty much
everything else.
It works how it does because it makes sense. The fact that drawing
single-pixel orthogonal lines means that you have to think about
what you're actually doing doesn't detract from that.
Fudging the math to make that particular case easier would only make sense
if that particular case was common, and it isn't. It only applies if the
primitives being rendered are being positioned based upon the screen's
pixel grid, and the overall combination of the model-view, projection and
viewport transformations happens to be an identity transformation. Which
is rarely the case.
Post by R.Wieser
*One "fun" thing I observed was when I, in ortho mode, did draw a line
loop and than a quad ontop of it using the same integer coordinates.
Two
Post by Nobody
Post by R.Wieser
line-loop sides peeped out from under the quad. And pardon me, but that
should *not* have happened.
That's like saying a coin toss which landed on tails "should have" landed
on heads.
For a filled primitive, having the edges lie exactly mid-way between two
rows of pixels is the ideal case, because it's clear-cut which pixels are
inside and which pixels are outside. For a line, it's the worst possible
case, as each set of pixels has exactly the same strength of claim to
being on the line.
For typical OpenGL usage, this isn't a problem. By the time that the 3D
coordinates have been subjected to the model-view and projection
transformations, projective division, and the viewport transformation, the
chances of the resulting line being exactly betwen two rows of pixels are
negligible. That situation only happens when you go out of your way
to create it.
Post by R.Wieser
The only "solution" I can think of is to give a odd-width line a different
treatment than a quad, thereby aliviating differences between the line and
the quad screen results. But I would thouroughly dislike that, as it
would be nothing more than a clumsy hack.
Which is why OpenGL doesn't try to do it. Being predictable, consistent
and rational are more important than being "intuitive".
And as time goes on, this issue will become progressively less relevant.
Even at 1920x1080 (which is about the lowest-resolution monitor you can
buy nowadays), single-pixel lines are barely visible. This is a
significant problem for legacy software which works in pixel coordinates
rather than e.g. a fraction of the window size. And as "4K" displays
(4096x2160 or 3840x2160) get cheaper, they'll start becoming the de facto
standard for PC monitors.
Nobody
2015-09-15 05:52:45 UTC
Permalink
On Mon, 14 Sep 2015 12:51:51 +0200, R.Wieser wrote:

Look, I'm not going to explain the entire OpenGL pipeline in detail,
*especially* to someone who is determined to ignore anything which they
don't want to hear.

But know this: you will experience exactly the same issue with every
other modern rendering API (meaning: uses floating-point coordinates with
an arbitrary affine or projective transformation), whether 2D or 3D.
OpenGL, DirectX, Cairo, HTML5 Canvas, SVG, PostScript, PDF, ..., they all
work the same way: rasterisation is based upon pixel centres while pixel
edges are aligned to integer coordinates.

If you want an API designed around 1990s VGA hardware, use SDL.
R.Wieser
2015-09-15 10:11:04 UTC
Permalink
Nobody,
Post by Nobody
*especially* to someone who is determined to ignore
anything which they don't want to hear.
I'm sorry, but all I hear from you is "you have to like what is as it is",
with *absolutily no explanation* why the, obviously creating problems,
method is so good.

So I will make it simple for you:

Why is, especially in ortho mode (where the Othto projections width and
height matches the one of the viewport and thus the rectangle of pixels on
the screen), an OpenGL (virtual) pixel placed 1) anywhere else than on the
screen pixel 2) on the most awkward of mathematical places, where the
slightest of rounding errors causes on-screen changes ?

Neither makes sense to me.
Post by Nobody
Look, I'm not going to explain the entire OpenGL pipeline in detail,
AFAICS it has absolutily nothing to do with that, only with how the OpenGL
virtual pixel grid is converted into a physical pixel grid.
Post by Nobody
But know this: you will experience exactly the same issue
with every other modern rendering [snip]
Which means that everyone working with any of those must have experienced
the same problem I do. Its therefore rather odd that I have not seen every
tutorial I've found regarding Ortho projection explaining this problem, and
how to deal with it.

As a closing remark: I'm not out to fight *you*. It's just that I cannot
accept any "yes, it causes problem, but that is how it works" kind of "just
deal with it" answers.

To be able to accept the problems it causes I need to understand the reason
why someone designed it that way (most likely to solve a fully other
problem. But if so which one ?).

Regards,
Rudy Wieser
Post by Nobody
Look, I'm not going to explain the entire OpenGL pipeline in detail,
*especially* to someone who is determined to ignore anything which they
don't want to hear.
But know this: you will experience exactly the same issue with every
other modern rendering API (meaning: uses floating-point coordinates with
an arbitrary affine or projective transformation), whether 2D or 3D.
OpenGL, DirectX, Cairo, HTML5 Canvas, SVG, PostScript, PDF, ..., they all
work the same way: rasterisation is based upon pixel centres while pixel
edges are aligned to integer coordinates.
If you want an API designed around 1990s VGA hardware, use SDL.
Nobody
2015-09-16 09:03:10 UTC
Permalink
Post by R.Wieser
Post by Nobody
*especially* to someone who is determined to ignore anything which they
don't want to hear.
I'm sorry, but all I hear from you is "you have to like what is as it is",
You don't have to like it, but if you want to use it, you have to make an
effort to understand how it works, rather than making assumptions which
aren't actually true.
Post by R.Wieser
with *absolutily no explanation* why the, obviously creating problems,
method is so good.
It's not an "obviously creating problems method". Your problems stem from
making incorrect assumptions, not from the the method.
Post by R.Wieser
Why is, especially in ortho mode (where the Othto projections width and
height matches the one of the viewport and thus the rectangle of pixels on
the screen), an OpenGL (virtual) pixel placed 1) anywhere else than on the
screen pixel 2) on the most awkward of mathematical places, where the
slightest of rounding errors causes on-screen changes ?
As I said before: a pixel isn't a point, it's a rectangle. A pixel
doesn't have a single, specific location.

To simplify matters, we can forget all about projections, and deal
directly in window coordinates. Let w and h be the width and height
(respectively) of the window in pixels.

The bottom-left corner of the bottom-left pixel is at the bottom-left
corner of the window, which is (0,0) in window coordinates.

Similarly, the top-right corner of the top-right pixel is at the top-right
corner of the window, which is (w,h) in window coordinates.

The top-right corner of the bottom-left pixel is at (1,1) in window
coordinates.

The centre of the bottom-left pixel is at (0.5,0.5) in window coordinates.

In short, window coordinates map a rectangular region of the screen to a
rectangular region of the Euclidean plane. That mapping is continuous
(i.e. defined over the reals, not the integers). Vertices (and other
positions, e.g. the raster position used for bitmap operations) are not
constrained to integer coordinates.

In theory, a line or polygon is an infinite set of points, a subset of
R^2. But a finite set of pixels cannot exactly represent those, so
rasterisation has to produce an approximation which attempts to minimise
the difference between the ideal and the achievable.

In the absence of anti-aliasing, rasterising a filled polygon affects
exactly those pixels whose centres lie within the polygon (i.e. within the
convex hull of the polygon's vertices).

There are other rules which could be used, but:

1. The reason for testing whether a specific point lies within the polygon
(rather than e.g. whether *any* part of the pixel lies inside the polygon)
is that in the case where two polygons share a common edge, any pixel
along that edge will belong to exactly one of the two polygons. This is of
fundamental importance when using read-modify-write operations such as
stencilling or glLogicOp(GL_XOR).

2. The reason for using the pixel's centre is that it is unbiased. Using
any other location would result in rasterised polygons exhibiting a net
shift whose magnitude depends upon the raster resolution.

In the absence of anti-aliasing, rasterising a line segment of width one
affects exactly those pixels for which the line intersects a diamond
inscribed within the pixel, i.e. some point (x,y) on the line segment
satisfies the constraint |x-xc|+|y-yc|<0.5 where (xc,yc) is the
coordinates of the pixel centre.

The main reasons for the diamond rule are a) that it can be efficiently
implemented in hardware, and b) that it guarantees that lines do not
contain gaps.

And again, the reason for using the pixel's centre is that it is unbiased.
On average, half of the affected pixels will lie on each side of the line.

This all works fine in practice, except for one specific case: when you
draw a line which is either exactly horizontal (i.e. every point on the
line has the same Y coordinate) or exactly vertical (i.e. every point on the
line has the same X coordinate), and the constant coordinate (X or Y)
happens to be exactly mid-way between pixel centres (i.e. the coordinate
is an integer).

In that case, the fact that it's unbiased on average doesn't help because
the fact that the perpendicular coordinate (X for a vertical line, Y for a
horizontal line) is constant, combined with the deterministic nature of
computer arithmetic, means that all of the pixels will end up falling on
the same side of the line.

Almost anything which involves rounding has pathological cases, and for
the rasterisation algorithm used by OpenGL (and almost everything else),
vertical or horizontal lines with integer window coordinates are the
pathological case. For filled polygons, vertical or horizontal edges whose
coordinates are an integer plus 0.5 are the pathological case.

Adding in transformations makes matters slightly worse. If you set an
orthographic projection which uses the window's dimensions in pixels, the
combination of the (user-defined) orthographic projection and the
(built-in) viewport transformation should theoretically be an identity
transformation. But in practice it will be slightly off because unless x
is a power of two, x*(1/x) typically won't be exactly 1.0 when using
floating-point arithmetic.

The overall error is sufficiently small that it shouldn't matter in
practice ... unless you've managed to construct a case where you're
consistently hitting the discontinuity in the rounding function.

In short, this can be summarised with an allegory: a man goes to the
doctor, and says "Doctor, when I do this ... it hurts"; to which the
doctor replies "So stop doing it!".
R.Wieser
2015-09-16 13:56:38 UTC
Permalink
Nobody,
Post by Nobody
You don't have to like it, but if you want to use it, you
have to make an effort to understand how it works
What did you think I was trying to do ?
Post by Nobody
rather than making assumptions which aren't actually true.
... and which assumptions would that be ?

As far as I can tell I did mention facts, and than mentioned why I do not
understand why it works/is done that way, as it creates problems.
Post by Nobody
Your problems stem from making incorrect assumptions,
not from the the method.
Than tell me what those "wrong assumptions" are please. You've hinted at
that a few times, but I've not seen any specifics (and neither does the
current post mention them).

But a remark:
I've been googeling quite a bit to try to find out whats going on and how to
fix it, and one of the things I found was that shifting the whole grid by
half a pixel horizontally as well as vertically (which I now have mentioned
a few times before, but not have seen you respond to yet. Why ?) would
certainly work for lines, but than would create problems for polygons.

In short: that "method" you are referring to seems to be made up from at
least two, which do not even agree with each other ... :-\
Post by Nobody
As I said before: a pixel isn't a point, it's a rectangle.
A pixel doesn't have a single, specific location.
....
Post by Nobody
The centre of the bottom-left pixel is at (0.5,0.5) in window coordinates.
Thank you for that explanation. It also indicates a problem when the term
"pixel" is used, as lthe ast time you metioned "rectangular pixels" I
assumed, from the context, that you ment OpenGLs virtual ones, instead of
the screens physical ones.

But a question: If I would use the exact same explanation, but define the
origin of the screen as the center* of the top-left pixel, with it ranging
from -1/2 pixel to +1/2 pixel, would that make the explanation invalid ? If
so, why ? If not ....

* The position of a lamp (or most any single-point lightsource) is normally
defined as its center, not somewhere on its outside. Why would it be
different for a pixel ?

I mean, if its only a problem of definitions than thats easy to solve. :-)
Post by Nobody
is that in the case where two polygons share a common edge,
any pixel along that edge will belong to exactly one of the two
polygons.
I think you've here mentioned the reason why a quad drawn ontop of a
lineloop (ofcourse using the same coordinates for both) does not fully
overlap the lineloop: because its *forced* to stop one pixel short of its
left/bottom end-coordinates, so it will not overlap an eventual next one.
A good choice, but not mentioned anywhere and as such not expected. :-\

I assumed that the above non-overlap was an effect of the problem I was/am
busy with, the non-alignment of the virtual and physical grid, and only
after a bout of googleing I realized that that might not be the case.

In other words: one problem solved (but more to go). :-)
Post by Nobody
2. The reason for using the pixel's centre is that it is unbiased.
Using any other location would result in rasterised polygons
exhibiting a net shift whose magnitude depends upon the raster
resolution.
Ehrmmm ... Although I think I understand what problem you are indicating
here, wasn't the problem not that OpenGL is *not* using the pixels center ?
Post by Nobody
for which the line intersects a diamond inscribed within the pixel
Yeah, I found that diamond too. Though I have to say that I do not quite
see how it, in a basic Ortho projection, would affect a single-pixel width
line drawn from the center of a physical pixel to the center of another
physical pixel (regardlesss of which coordinates are used). The endpoints
would *always* be drawn where they where indicated. Curently I cannot be
sure of that ...
Post by Nobody
because unless x is a power of two, x*(1/x) typically won't
be exactly 1.0 when using floating-point arithmetic.
And thats *exactly* why an OpenGL pixel should *not* be placed, when using a
basic ortho projection and integer coordinates, on the border of two
physical ones.
Post by Nobody
The overall error is sufficiently small that it shouldn't matter
in practice ...
Guess again: Thats how this thread started (read the subject line).
Post by Nobody
unless you've managed to construct a case where you're
consistently hitting the discontinuity in the rounding function.
Yeah, funny that: I'm using the *most basic* of setups (ortho projection
matching the viewport size, integer coordinates for any used vertex), and
I'm already able to construct that case.

Let me think about it ..... Nope, I get the strong, almost definite feeling
you're bullshitting me here. Sorry.
Post by Nobody
In short, this can be summarised with an allegory: a man goes
to the doctor, and says "Doctor, when I do this ... it hurts"; to
which the doctor replies "So stop doing it!".
Well, in my country we use that one as a joke, indicating the non-usability
of such an answer (which ignores the problem, but only wants to get rid of
the symptoms). I'm not at all sure if you ment it that way, but I think
its quite fitting. :-(

Thanks for your attempt to help me though.

Regards,
Rudy Wieser
Post by Nobody
Post by R.Wieser
Post by Nobody
*especially* to someone who is determined to ignore anything which they
don't want to hear.
I'm sorry, but all I hear from you is "you have to like what is as it is",
You don't have to like it, but if you want to use it, you have to make an
effort to understand how it works, rather than making assumptions which
aren't actually true.
Post by R.Wieser
with *absolutily no explanation* why the, obviously creating problems,
method is so good.
It's not an "obviously creating problems method". Your problems stem from
making incorrect assumptions, not from the the method.
Post by R.Wieser
Why is, especially in ortho mode (where the Othto projections width and
height matches the one of the viewport and thus the rectangle of pixels on
the screen), an OpenGL (virtual) pixel placed 1) anywhere else than on the
screen pixel 2) on the most awkward of mathematical places, where the
slightest of rounding errors causes on-screen changes ?
As I said before: a pixel isn't a point, it's a rectangle. A pixel
doesn't have a single, specific location.
To simplify matters, we can forget all about projections, and deal
directly in window coordinates. Let w and h be the width and height
(respectively) of the window in pixels.
The bottom-left corner of the bottom-left pixel is at the bottom-left
corner of the window, which is (0,0) in window coordinates.
Similarly, the top-right corner of the top-right pixel is at the top-right
corner of the window, which is (w,h) in window coordinates.
The top-right corner of the bottom-left pixel is at (1,1) in window
coordinates.
The centre of the bottom-left pixel is at (0.5,0.5) in window coordinates.
In short, window coordinates map a rectangular region of the screen to a
rectangular region of the Euclidean plane. That mapping is continuous
(i.e. defined over the reals, not the integers). Vertices (and other
positions, e.g. the raster position used for bitmap operations) are not
constrained to integer coordinates.
In theory, a line or polygon is an infinite set of points, a subset of
R^2. But a finite set of pixels cannot exactly represent those, so
rasterisation has to produce an approximation which attempts to minimise
the difference between the ideal and the achievable.
In the absence of anti-aliasing, rasterising a filled polygon affects
exactly those pixels whose centres lie within the polygon (i.e. within the
convex hull of the polygon's vertices).
1. The reason for testing whether a specific point lies within the polygon
(rather than e.g. whether *any* part of the pixel lies inside the polygon)
is that in the case where two polygons share a common edge, any pixel
along that edge will belong to exactly one of the two polygons. This is of
fundamental importance when using read-modify-write operations such as
stencilling or glLogicOp(GL_XOR).
2. The reason for using the pixel's centre is that it is unbiased. Using
any other location would result in rasterised polygons exhibiting a net
shift whose magnitude depends upon the raster resolution.
In the absence of anti-aliasing, rasterising a line segment of width one
affects exactly those pixels for which the line intersects a diamond
inscribed within the pixel, i.e. some point (x,y) on the line segment
satisfies the constraint |x-xc|+|y-yc|<0.5 where (xc,yc) is the
coordinates of the pixel centre.
The main reasons for the diamond rule are a) that it can be efficiently
implemented in hardware, and b) that it guarantees that lines do not
contain gaps.
And again, the reason for using the pixel's centre is that it is unbiased.
On average, half of the affected pixels will lie on each side of the line.
This all works fine in practice, except for one specific case: when you
draw a line which is either exactly horizontal (i.e. every point on the
line has the same Y coordinate) or exactly vertical (i.e. every point on the
line has the same X coordinate), and the constant coordinate (X or Y)
happens to be exactly mid-way between pixel centres (i.e. the coordinate
is an integer).
In that case, the fact that it's unbiased on average doesn't help because
the fact that the perpendicular coordinate (X for a vertical line, Y for a
horizontal line) is constant, combined with the deterministic nature of
computer arithmetic, means that all of the pixels will end up falling on
the same side of the line.
Almost anything which involves rounding has pathological cases, and for
the rasterisation algorithm used by OpenGL (and almost everything else),
vertical or horizontal lines with integer window coordinates are the
pathological case. For filled polygons, vertical or horizontal edges whose
coordinates are an integer plus 0.5 are the pathological case.
Adding in transformations makes matters slightly worse. If you set an
orthographic projection which uses the window's dimensions in pixels, the
combination of the (user-defined) orthographic projection and the
(built-in) viewport transformation should theoretically be an identity
transformation. But in practice it will be slightly off because unless x
is a power of two, x*(1/x) typically won't be exactly 1.0 when using
floating-point arithmetic.
The overall error is sufficiently small that it shouldn't matter in
practice ... unless you've managed to construct a case where you're
consistently hitting the discontinuity in the rounding function.
In short, this can be summarised with an allegory: a man goes to the
doctor, and says "Doctor, when I do this ... it hurts"; to which the
doctor replies "So stop doing it!".
Nobody
2015-09-17 10:36:44 UTC
Permalink
Post by R.Wieser
Post by Nobody
As I said before: a pixel isn't a point, it's a rectangle. A pixel
doesn't have a single, specific location.
....
Post by Nobody
The centre of the bottom-left pixel is at (0.5,0.5) in window
coordinates.
Thank you for that explanation. It also indicates a problem when the term
"pixel" is used, as lthe ast time you metioned "rectangular pixels" I
assumed, from the context, that you ment OpenGLs virtual ones, instead of
the screens physical ones.
I don't know what these "virtual pixels" you describe are.
Post by R.Wieser
But a question: If I would use the exact same explanation, but define the
origin of the screen as the center* of the top-left pixel, with it ranging
from -1/2 pixel to +1/2 pixel, would that make the explanation invalid ?
If so, why ? If not ....
OpenGL defines a number of coordinate systems. Coordinates passed to
OpenGL are interpreted in the coordinate systems which it defines. While
you can define your own coordinate system for the purpose of exposition,
I really don't seen any point; it would just create confusion, as you'd
continually need to clarify whether you were talking about your coordinate
system or OpenGL's.
Post by R.Wieser
* The position of a lamp (or most any single-point lightsource) is
normally defined as its center, not somewhere on its outside. Why would it
be different for a pixel ?
A pixel doesn't have a position. How many times do I have to keep saying
this?

A pixel is an area, a subset of R^2 containing an infinite number of
points, each of which has a distinct position.
Post by R.Wieser
Post by Nobody
is that in the case where two polygons share a common edge, any pixel
along that edge will belong to exactly one of the two polygons.
I think you've here mentioned the reason why a quad drawn ontop of a
lineloop (ofcourse using the same coordinates for both) does not fully
overlap the lineloop: because its *forced* to stop one pixel short of its
left/bottom end-coordinates, so it will not overlap an eventual next one.
A good choice, but not mentioned anywhere and as such not expected. :-\
The omission of the endpoint is a separate issue, but has a similar origin
(certain operations not modifying a pixel multiple times).

The fact that a rasterised line between two points is neither wholly
inside nor wholly outside a rasterised polygon containing that edge is
related to the fact that the same edge can be shared by two different
polygons (one on each side).

Which polygon should the line be inside or outside? The answer can't be
"the one I'm actually drawing" because drawing operations are independent;
the rasterisation of a line can't change based upon whether or not you
also draw a polygon using the same vertices.
Post by R.Wieser
Post by Nobody
2. The reason for using the pixel's centre is that it is unbiased.
Using any other location would result in rasterised polygons exhibiting
a net shift whose magnitude depends upon the raster resolution.
Ehrmmm ... Although I think I understand what problem you are indicating
here, wasn't the problem not that OpenGL is *not* using the pixels center ?
No. Your problem is that rasterisation (for both lines and polygons) is
based upon pixel centers, whose window coordinates are always an
integer-plus-a-half, not integers.
Post by R.Wieser
Post by Nobody
for which the line intersects a diamond inscribed within the pixel
Yeah, I found that diamond too. Though I have to say that I do not
quite see how it, in a basic Ortho projection, would affect a
single-pixel width line drawn from the center of a physical pixel to the
center of another physical pixel
It doesn't. If you draw between pixel centres, you don't have a problem.
If you draw between pixel corners (i.e. use integer window coordinates),
the problem occurs.
Post by R.Wieser
Post by Nobody
because unless x is a power of two, x*(1/x) typically won't be exactly
1.0 when using floating-point arithmetic.
And thats *exactly* why an OpenGL pixel should *not* be placed, when
using a basic ortho projection and integer coordinates, on the border of
two physical ones.
Pixels aren't "placed" anywhere; they're areas, not points (I'm starting
to sound like a stuck gramophone here).
Post by R.Wieser
Post by Nobody
unless you've managed to construct a case where you're consistently
hitting the discontinuity in the rounding function.
Yeah, funny that: I'm using the *most basic* of setups (ortho projection
matching the viewport size, integer coordinates for any used vertex),
Which is exactly what you SHOULDN'T be doing. Integer coordinates
correspond to the edges and corners of pixels, i.e. the points exactly
between pixels. Which are the worst points to use if you're trying to draw
lines such that specific pixels are affected.

If you want to render filled polygons, then integer coordinates are ideal
(i.e. they ensure that the edges don't fall on pixel centres, resulting in
the inside-ness test being a tie which is decided by rounding error).
R.Wieser
2015-09-17 16:18:53 UTC
Permalink
Nobody,
Post by Nobody
I don't know what these "virtual pixels" you describe are.
Nope, I'm not going to try to explain that to you for ... the fourth or
fifth time. Just accept that you never will.
Post by Nobody
While you can define your own coordinate system for
the purpose of exposition,
And you will never understand that that coordinate system you keep using is
as abitrary as a roll of the dice.
Post by Nobody
A pixel doesn't have a position. How many times do I have to
keep saying this?
Until you come up with a position that *doesn't* flip-flop from one
explanation to another. Like saying that a pixel is a rectangle, where the
top-left one ranges from 0,0 to 1,1. That certainly looks like a
positional indication to me ....
Post by Nobody
A pixel is an area, a subset of R^2 containing an infinite number of
points, each of which has a distinct position.
.. and I don't know about that screen you are looking at, but on mine (the
physical) pixels have a fixed position/location.

And those "points" you are talking about ? Guess what: Thats what I ment
with "virtual pixels". In your system the pixels you are talking about do
not exist *at all*, and much less are a rectangle or have dimensions.

What you do not seem to grasp is that those pixels *you* are talking about
are, in fact, representations / shadows of the physical pixels, the ones
those "points" of yours need to be translated to. Thru a set of
translations and scalings no less. Which causes *your* "pixels" to have
different sizes depending on a combination of factors.


...And I'm going to stop here, not even bothering to read the rest. I
don't think you want to understand what I asked, nor what I said later on.

Lets face it: I've mentioned the stupidity of placing (your) points on the
border of two (of my) pixels a few times now (when placing them using
integer coordinates), but you've fully ignored it. Why ? Most likely
because its not in line with your "its GOOD!" conviction (either that, or
you have a remarkable selective reading).

You've also tried to let me/us believe that the most basic of Ortho setups
is actually "a constructed case", and no mentioning of mine about it to the
opposite could evoke a reaction.

Either you're not half as smart as you think you are, or you are activily
trying to lie to me.

So, go pester somebody else.

Goodbye.
Rudy Wieser
Post by Nobody
Post by R.Wieser
Post by Nobody
As I said before: a pixel isn't a point, it's a rectangle. A pixel
doesn't have a single, specific location.
....
Post by Nobody
The centre of the bottom-left pixel is at (0.5,0.5) in window coordinates.
Thank you for that explanation. It also indicates a problem when the term
"pixel" is used, as lthe ast time you metioned "rectangular pixels" I
assumed, from the context, that you ment OpenGLs virtual ones, instead of
the screens physical ones.
I don't know what these "virtual pixels" you describe are.
Post by R.Wieser
But a question: If I would use the exact same explanation, but define the
origin of the screen as the center* of the top-left pixel, with it ranging
from -1/2 pixel to +1/2 pixel, would that make the explanation invalid ?
If so, why ? If not ....
OpenGL defines a number of coordinate systems. Coordinates passed to
OpenGL are interpreted in the coordinate systems which it defines. While
you can define your own coordinate system for the purpose of exposition,
I really don't seen any point; it would just create confusion, as you'd
continually need to clarify whether you were talking about your coordinate
system or OpenGL's.
Post by R.Wieser
* The position of a lamp (or most any single-point lightsource) is
normally defined as its center, not somewhere on its outside. Why would it
be different for a pixel ?
A pixel doesn't have a position. How many times do I have to keep saying
this?
A pixel is an area, a subset of R^2 containing an infinite number of
points, each of which has a distinct position.
Post by R.Wieser
Post by Nobody
is that in the case where two polygons share a common edge, any pixel
along that edge will belong to exactly one of the two polygons.
I think you've here mentioned the reason why a quad drawn ontop of a
lineloop (ofcourse using the same coordinates for both) does not fully
overlap the lineloop: because its *forced* to stop one pixel short of its
left/bottom end-coordinates, so it will not overlap an eventual next one.
A good choice, but not mentioned anywhere and as such not expected. :-\
The omission of the endpoint is a separate issue, but has a similar origin
(certain operations not modifying a pixel multiple times).
The fact that a rasterised line between two points is neither wholly
inside nor wholly outside a rasterised polygon containing that edge is
related to the fact that the same edge can be shared by two different
polygons (one on each side).
Which polygon should the line be inside or outside? The answer can't be
"the one I'm actually drawing" because drawing operations are independent;
the rasterisation of a line can't change based upon whether or not you
also draw a polygon using the same vertices.
Post by R.Wieser
Post by Nobody
2. The reason for using the pixel's centre is that it is unbiased.
Using any other location would result in rasterised polygons exhibiting
a net shift whose magnitude depends upon the raster resolution.
Ehrmmm ... Although I think I understand what problem you are indicating
here, wasn't the problem not that OpenGL is *not* using the pixels center ?
No. Your problem is that rasterisation (for both lines and polygons) is
based upon pixel centers, whose window coordinates are always an
integer-plus-a-half, not integers.
Post by R.Wieser
Post by Nobody
for which the line intersects a diamond inscribed within the pixel
Yeah, I found that diamond too. Though I have to say that I do not
quite see how it, in a basic Ortho projection, would affect a
single-pixel width line drawn from the center of a physical pixel to the
center of another physical pixel
It doesn't. If you draw between pixel centres, you don't have a problem.
If you draw between pixel corners (i.e. use integer window coordinates),
the problem occurs.
Post by R.Wieser
Post by Nobody
because unless x is a power of two, x*(1/x) typically won't be exactly
1.0 when using floating-point arithmetic.
And thats *exactly* why an OpenGL pixel should *not* be placed, when
using a basic ortho projection and integer coordinates, on the border of
two physical ones.
Pixels aren't "placed" anywhere; they're areas, not points (I'm starting
to sound like a stuck gramophone here).
Post by R.Wieser
Post by Nobody
unless you've managed to construct a case where you're consistently
hitting the discontinuity in the rounding function.
Yeah, funny that: I'm using the *most basic* of setups (ortho projection
matching the viewport size, integer coordinates for any used vertex),
Which is exactly what you SHOULDN'T be doing. Integer coordinates
correspond to the edges and corners of pixels, i.e. the points exactly
between pixels. Which are the worst points to use if you're trying to draw
lines such that specific pixels are affected.
If you want to render filled polygons, then integer coordinates are ideal
(i.e. they ensure that the edges don't fall on pixel centres, resulting in
the inside-ness test being a tie which is decided by rounding error).
Loading...