OpenGL - 每个三角形的像素数不正确

时间:2018-06-15 20:13:15

标签: c++ opengl glm-math

我使用Blender创建一个简单的多维数据集,并在我的openGL C ++代码中使用Assimp读取它。立方体的6个面中的每一个被分成两个三角形。我用不同的颜色为每个三角形着色(蓝色= 0,绿色= 0,但红色不同于三角形到另一个)。

为了使立方体可视化,我使用了正射投影。我将max_vertice称为多维数据集中顶点的最大值,fac_max_vertice是我设置为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);

我根据角度theta和phi(固定距离)围绕立方体旋转相机:

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)); 

我使用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));

其中width_here和height_here是窗口的宽度和高度(请注意,我将变量称为红色,但我看每个组件为红色,蓝色和绿色)

一旦我得到一个像素的颜色,我就为像素分配了相应的面(与像素颜色相同的面)。

然后我计算每张脸的像素数。

当相机正好放在脸部前方时(例如,theta = phi = 0),每个脸部的像素数对于脸部的两个三角形完全相同,这是有意义的。然而,这是我认为存在错误的地方,当我将相机旋转一定值(例如,phi = 10°)时,两个面之间的像素数不再相同。它应该是相同的,因为面部是平的,因此从相机看到的像素数对于2个三角形完全相同。

例如,在附图中,对于大脸的2个三角形中的一个,像素的数量是21931,但是对于相同大脸的另一个三角形,像素的数量是21845。对于低入射率的面部也会发生同样的错误(也有两个三角形,但颜色彼此接近):一个三角形为1105像素,另一个三角形为1199像素。

你知道会发生什么吗?

cube

1 个答案:

答案 0 :(得分:4)

有几个因素会导致两个不同的三角形用不同数量的像素进行栅格化:

多重采样

当三角形的边缘不完全出现在像素的边界上,并且启用了多重采样时,结果像素将包含一个混合值,该值可能不等于给定三角形的颜色,或任何周围的三角形。因此,计算给定像素颜色的实例必然会导致计数不同。

视角

当您使用透视矩阵作为投影矩阵(与正交矩阵相对)时,不同位置的两个相同三角形将具有不同的大小。三角形通常会越远离屏幕中心越远。

取向

两个在数学上相同的三角形将根据它们的位置看到少量光栅化伪像,特别是如果它们被旋转(它们在您的示例中)。用于确定是否应该栅格化特定像素的光栅化器算法不会对面向不同方向的边缘进行完全相同的评估。

闭塞

在您的示例中,两个三角形彼此直接相邻。这意味着其中一个三角形将在Rasterizer中获得优先权。这可能是深度测试或小浮点错误或任何其他因素的结果。它甚至不能保证是确定性的,因为OpenGL实现允许在如何做出这些决策方面留有少量余地,至少在涉及具有相同深度的片段时;这是Z-Fighting的根本原因。

结论

你的基本假设是,“这两个相同大小的三角形应该具有相同数量的渲染像素”显然是错误的。高度受限的情况(例如在您的示例中,相机以完美平坦的角度锁定)可能会产生两个具有相同像素数的三角形,但在任何其他情况下,它们都不会。这是现代图形架构的自然结果。如果您打算让两个对象具有完全相同的像素数,则需要切换到基于整数的渲染,或采用一些非常不寻常的实践。我建议你研究“复古风格”游戏如何处理以低“有效分辨率”渲染游戏的任务,然后注意这些游戏中的许多可能会显示你观察到的很多相同的怪癖。