Question

Let pa be a point at (0.5, y) and pb at (5.5, y). If we draw a line segment from pa to pb we get a 5 pixel segment on x axis. The question is where exactly these pixels are?

According to the OpenGL ES 2.0 specification 3.4.1:

When pa and pb lie on fragment centers, this characterization of fragments reduces to Bresenham’s algorithm with one modification: lines produced in this description are “half-open,” meaning that the final fragment (corresponding to pb) is not drawn.

If we draw a segment from pa to pb we get pixels 1 to 5 (x coordinate). pa is on the centre of the first pixel and pb is on the centre of the 6th one. If we draw from pb to pa we get 2 to 6. This is the result I'm getting on iPhone 4s. But on Android (Nexus 7 and emulator) the result is always 1 to 5 (direction doesn't matter). The drawing code is exactly the same (using NDK).

So the question is which behaviour is a correct one? And what workarounds should I use to have the same result on both systems?

EDIT

On Mac OS if you run the following code (using simple NSOpenGLView subclass):

glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f, 0.85f, 0.35f);
float pa = 0.5;
float pb = 5.5;
float y =  5.5;
glOrtho(-50, 50, -50, 50, -1, 1);
glBegin(GL_LINES);
{
    //pa to pb - lower line
    glVertex3f(pa, y, 0.0);
    glVertex3f(pb, y, 0.0);
    ++y;
    //pb to pa - upper line
    glVertex3f(pb, y, 0.0);
    glVertex3f(pa, y, 0.0);
}
glEnd();
glFlush();

You get this result: enter image description here

screen shot

So this is the expected result. And it seems that Nexus 7 has a different interpretation of a spec or I might need to enable some special setting.

EDIT 2:

My emulator wasn't fitting into the screen and it was rescaling screen output and it created an illusion that emulator has the same problem as the device. After taking a screenshot through the DDMS it was obvious that emulator produces the expected result: emulator

But device is producing the following result: nexus_7

To reproduce this replace the contents of gl_code.cpp file with the following code and run hello-gl2 ndk sample project.

Was it helpful?

Solution

Quoth the spec you linked to:

Because the initial and final conditions of the diamond-exit rule may be difficult to implement, other line segment rasterization algorithms are allowed, subject to the following rules:

  1. The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in either x or y window coordinates from a corresponding fragment produced by the diamond-exit rule.

Thus, it appears to be a legal deviation, unfortunately.

For workarounds, I'd myself try using coordinates such as 0.25 or 0.75 instead of 0.5 if they might produce the same result on both rasterizers.

Or rasterize a single line in the beginning and see which rule your rasterizer is using and adapt all coordinates later to that.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top