为什么 OpenGL 会切断多边形(即使此设置已禁用)?

Why OpenGL cut off polygons (even if this settings is disabled)?

I read similar suggested questions and their solutions, but could not find an answer.

我正在尝试在 OpenGL 中使用等距视图绘制场景。

绘图功能:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glRotatef(atan(0.5f) * 180.0f / PI, 1.0f, 0.0f, 0.0f);
glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
    
glBegin(GL_QUADS);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 1.0f);
glEnd();

glPopMatrix();

最后,我得到了这个结果。相机确实有一个等距投影,但由于某些原因,多边形被剪裁了。

如果我在绘制四边形之前加上glTranslatef(-0.8f, 0, -0.8f),结果如下:

问题是我没有对 OpenGL 渲染应用任何优化。但是为什么多边形一定要切掉呢?

多边形被观察体积的近平面或远平面裁剪。

不设置投影矩阵时,viewspace、clipspace和normalized devicespace是一样的。归一化设备 space 是一个独特的立方体,其左、下、近距离为 (-1, -1, -1),右、上、远距离为 (1, 1, 1)。所有不在这个立方体内部的几何体都被剪掉了。

实际上你画了一个边长为1的四边形。四边形的一个顶点在视图的原点(0, 0, 0)。四边形围绕原点旋转 glRotate。由于四边形的对角线长度为sqrt(2.0),因此旋转四边形的一个顶点被近平面或远平面裁剪。

如果你构建并旋转一个中心为(0, 0 ,0)的四边形,它不会被裁剪,因为从中心到每个顶点的长度是sqrt(2.0)/2.0。也就是小于1(到远近平面的距离形成视体积的中心)

glBegin(GL_QUADS);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(-0.5f, 0.0f, -0.5f);
glVertex3f( 0.5f, 0.0f, -0.5f);
glVertex3f( 0.5f, 0.0f,  0.5f);
glVertex3f(-0.5f, 0.0f,  0.5f);
glEnd();

分别

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glRotatef(atan(0.5f) * 180.0f / PI, 1.0f, 0.0f, 0.0f);
glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);

glTranslate(-0.5f, 0.0f, -0.5f);

glBegin(GL_QUADS);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 1.0f);
glEnd();

或者您可以设置 Orthographic projection, which enlarges the viewing volume by glOrtho:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glOrtho(-1.0, 1.0, -1.0, 1.0, -2.0, 2.0);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glRotatef(atan(0.5f) * 180.0f / PI, 1.0f, 0.0f, 0.0f);
glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);    

glBegin(GL_QUADS);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 1.0f);
glEnd();