0
votes

I create a simple cube with Blender and reads it with Assimp in my openGL C++ code. Each of the 6 faces of the cube is divided into two triangles. I color each triangle with a different color (blue =0, green = 0, but red is different from a triangle to another).

To visualize the cube, I use an ortho projection. I call max_vertice the maximum value of the vertice in the cube and fac_max_vertice is a number that I set to 2:

glm::mat4 Projection = glm::ortho<float>(-max_vertice* fac_max_vertice,max_vertice* fac_max_vertice,-max_vertice* fac_max_vertice,max_vertice* fac_max_vertice, 0, 2 * max_vertice* fac_max_vertice);

I rotate the camera around the cube according to the angles theta and phi (at a fixed distance):

distance_camera = maximum value of vertice*fac_max_vertice; // fixed
x_camera = distance_camera * sin(theta) * cos(phi); // phi and theta can vary
y_camera = distance_camera * sin(theta) * sin(phi);
z_camera = distance_camera * cos(theta);
glm::vec3 camera = glm::vec3(x_camera, y_camera, z_camera);                                                                                                                                 
glm::mat4 View = glm::lookAt(camera, glm::vec3(0,0,0), glm::vec3(0,1,0)); 

I identify the color of each pixel using glReadPixels:

unsigned char *red = (unsigned char *)malloc(3*width_here*height_here*sizeof(unsigned char *));
glReadPixels(0, 0, width_here, height_here, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)(red));

where width_here and height_here are the width and height of the window (note that I call the variable red but I look at each component red, blue, and green)

Once I have the color of a pixel, I assign the pixel its corresponding face (the face that has the same color of the pixel).

I then count the number of pixels per face.

When the camera is placed right in front of a face (for example, theta = phi = 0), the number of pixels per face is exactly the same for the two triangles of the face, which makes sense. However, and this is where I think there is an error, when I rotate the camera by a certain value (for example, phi = 10°), the number of pixels is not the same between the two faces anymore. It should be the same though, since the face if flat so number of pixels seen from the camera is exactly the same for the 2 triangles.

For example, in the figure attached, the number of pixels is 21931 for one of the 2 triangles of the large face, but the number of pixels is 21845 for the other triangle of the same large face. The same bug happens for the face that is seen with a low incidence (there are two triangles too but the colors are close to each other): 1105 pixels for one triangle and 1199 pixels for the other triangle.

Do you have any idea of what could be happening?

cube

1
You asked this exact same question half a month ago, and the same observation made then can be made now: it does not follow that two triangles, even of the same size, will get the same number of pixels rasterized when rendered in different positions, especially if any form of transformations have been performed on the model, view, or projection. - Xirema
I did ask the same question but without enough details so I thought that there could have been a misunderstanding on my problem. Thank you for your answer, though. - Zola
It's good that you added a proper MCVE this time. Definitely continue that practice for any other questions you submit here. - Xirema
"The same bug happens for the face that is seen with a low incidence" it is not a "bug". It is the result of the rasterization rules. It actually works as intended, and fully conforming to the spec. That you you even see the same pixel count for both triangles at zero angle is more by chance than anything else. - derhass

1 Answers

4
votes

There are several factors that will cause two different triangles to rasterize with different numbers of pixels:

Multisampling

When the edges of Triangles don't occur exactly on the boundary of a pixel, and multisampling is enabled, the resulting pixel is going to contain a blended value, which will probably not be equal to the color of a given triangle, or any of the surrounding triangles. So counting the instances of a given pixel color will necessarily result in the counts being different.

Perspective

When you're using a Perspective Matrix as your Projection matrix (as opposed to an Orthogonal matrix), two identical triangles in different positions are going to have different sizes. Triangles will generally be more stretched the farther away from the center of the screen they are.

Orientation

Two triangles that are mathematically identical are going to see small amounts of rasterization artifacting based on where they're positioned, especially if they're rotated (which they are in your example). The Rasterizer's algorithm for determining whether it should rasterize a specific pixel is not going to evaluate exactly the same for an edge facing a different direction.

Occlusion

In your example, two triangles are directly adjacent to each other. This means that one of the triangles is going to get priority in the Rasterizer. This could be the result of Depth Testing, or small floating-point errors, or any number of other factors. It's not even guaranteed to be deterministic, as an OpenGL implementation is permitting a small amount of leeway in terms of how these decisions get made, at least when it comes to fragments that have the same depth; this is the root cause of Z-Fighting.

Conclusion

Your base assumption, that "these two identically-sized triangles should have identical quantities of rendered pixels" is patently false. Highly constrained circumstances (like in your example, a camera locked on at a perfectly flat angle) may yield two triangles that have identical pixel counts, but under any other circumstances, they won't. This is a natural consequence of modern graphics architecture. If you intend for two objects to have exactly equal pixel-counts, you need to switch to Integer-based rendering, or employ some highly unusual practices. I'd recommend you research how "retro-style" games handle the task of rendering games with low "effective resolutions", and then note that many of these games probably display a lot of the same quirks you're observing.