Reputation: 53
I'm trying to draw a point at every pixel on the screen but I'm getting a weird anomaly: two red lines, one vertical, one horizontal:
My setup is like this:
I've got an ortho projection matrix like this:
glm::mat4 projection=glm::ortho(0.f, screen_width-1.f, 0.f, screen_height-1.f, 1.f, -1.f);
It's just setting the opengl coordinate system to be the same size as the screen's pixel dimensions.
Then, I'm creating filling the data into a vector like this:
for (int i=0; i<screen_height; ++i){
for (int j=0; j<screen_width; ++j){
idata.push_back(j);
idata.push_back(i);
idata.push_back(1);
}
}
I'm uploading integers into a VBO with this:
glBufferData(GL_ARRAY_BUFFER, sizeof(GLint)*idata.size(), &idata[0], GL_DYNAMIC_DRAW);
Setting up the attributes like so:
glVertexAttribIPointer(0, 3, GL_INT, 3*sizeof(GLint), (void *)(0*sizeof(GLint)));
glEnableVertexAttribArray(0);
This is the layout of my shader:
layout (location=0) in ivec3 position;
And this is my draw call:
glDrawArrays(GL_POINTS, 0, idata.size()/3);
Upvotes: 2
Views: 1523
Reputation: 45352
That's a rounding issue, because you did set up the projection in a very weird way:
glm::ortho(0.f,screen_width-1.f,0.f,screen_height-1.f,1.f,-1.f)
In OpenGL's window space, pixels are an actual area (of squares of size 1x1
).
So, If your screen is for example 4 pixel wide, this is what you get in terms of pixels
+--+--+--+--+
|0 |1 |2 |3 | integer pixel coors
...
However, the space you work in is continuous (in principle, at least), adn OpenGL's window space will go from 0 to 4 (not 3), which makes perfect sense as there are four pixels, and each pixel being one unit wide:
0 1 2 3 4 OpenGL window space
+--+--+--+--+
|0 |1 |2 |3 | integer pixel coords
....
Using OpenGL's window space conventions, the pixel centers lie at half-integer coordinates.
Now you're not drawing in OpenGL window space directly, but you can set up transformation to basically undo the viewport transform (which goes from NDC to window space) to get a pixel-exact mapping. But you didn't do that. what you did instead is:
3/4 9/4
0 6/4 3 your coordinate system
+--+--+--+--+
|0 |1 |2 |3 | integer pixel coords
....
And you're draw at full integers in that weird system, which just does not map very well to the actual pixels.
So you should do
glm::ortho(0.f,screen_width,0,screen_height,1.f,-1.f)
However, since you seem to be drawing at integer positions, you end up drawing exactly at the pixel corners, and might still see some rounding issues (and the rounding direction will be up to the implementation, as per the spec).
So, you better shift it so that integer coordinates lie at pixel centers
glm::ortho(-0.5f, screen_width-0.5f, -0.5f, screen_height-0.5f, 1.f, -1.f)
0.5 2.5
-0.5 1.5 3.5 your coordinate system
+--+--+--+--+
|0 |1 |2 |3 | integer pixel coords
....
Upvotes: 3