我正在尝试获得一些 OpenGL 的实践经验,因此我一直在编写一些基本程序。下面的简短程序是我第一次尝试渲染一个实体对象——一个旋转的立方体——但出于某种原因,一些背面的多边形似乎被绘制在正面的多边形之上。我的问题是什么可能导致这种情况?它与深度缓冲区有关吗?我发现在这种情况下启用面部剔除会隐藏效果,但为什么有必要这样做呢?一张被更近的脸遮挡的脸不应该被隐藏吗?
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
typedef struct{
int width;
int height;
char * title;
} window;
window win;
float theta = 0;
const float rotRate = 0.05;//complete rotations per second
int lastTime;
const float verts[][3] = {
{0.0,0.0,0.0},
{1.0,0.0,0.0},
{0.0,1.0,0.0},
{0.0,0.0,1.0},
{0.0,1.0,1.0},
{1.0,0.0,1.0},
{1.0,1.0,0.0},
{1.0,1.0,1.0}};
const int faceIndices[][4] = {
{3,5,7,4},//front
{1,0,2,6},//back
{4,7,6,2},//top
{0,1,5,3},//bottom
{5,1,6,7},//right
{0,3,4,2}};//left
void display(){
//timing and rotation
int currentTime = glutGet(GLUT_ELAPSED_TIME);
int dt = lastTime - currentTime;
lastTime = currentTime;
theta += (float)dt/1000.0*rotRate*360.0;
if (theta > 360.0) theta += -360.0;
//draw
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -5.0);
glRotatef(theta, 0.0, 1.0, 0.0);
glTranslatef(-1.0,-1.0,-1.0);
glScalef(2.0, 2.0, 2.0);
int f;
for(f=0; f<6;f++){
glBegin(GL_POLYGON);
int v;
for(v=0; v<4; v++){
glColor3fv(verts[faceIndices[f][v]]);
glVertex3fv(verts[faceIndices[f][v]]);
}
glEnd();
}
glutSwapBuffers();
}
void initializeGLUT(int * argc, char ** argv){
glutInit(argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(win.width, win.height);
glutCreateWindow("OpenGL Cube");
glutDisplayFunc(display);
glutIdleFunc(display);
}
void initializeGL(){
//Setup Viewport matrix
glViewport(0,0,win.width, win.height);
//Setup Projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45,(float) win.width/win.height, 0.1, 100.0);
//Initialize Modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//Other
glClearColor(0.0, 0.0, 0.0, 0.0);
glClearDepth(1.0);
}
int main(int argc, char** argv){
win.width = 640;
win.height = 480;
initializeGLUT(&argc, argv);
initializeGL();
glutMainLoop();
return 0;
}
最佳答案
Does it have something to do with the depth buffer?
是的,这是一个深度缓冲问题,您在代码中启用了深度缓冲,但显然您丢失了一些步骤,以使用深度缓冲
- 通过调用
glEnable(GL_DEPTH_TEST)
启用深度测试 - 通过 glDepthFunc 设置深度测试函数,GL_LEQUAL 是大多数情况下的推荐选择,
glDepthFunc(GL_LEQUAL);
默认值为 GL_LESS。 - 调用
glClearDepth
设置清除值,初始值为1.0,如果需要默认值,这一步不是必须的。 - 不要忘记在绘制之前清除深度位,
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
I've found that enabling face culling will hide the effect in this case, but why should that be necessary?
OpenGL默认不剔除任何人脸,推荐选项为
- 定义Clock Wise顺序的顶点为背面(这也是OpenGL的选择)
- 必要时剔除背面。
在你的例子中,你定义的多边形顶点都是逆时针顺序,所以它们默认都是正面,你只需要剔除背面以防止它们绘制,所以下面的代码也解决了你的问题。
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glCullFace(GL_BACK);
Shouldn't a face which is occluded by a nearer face be hidden regardless?
是的,这是有道理的,因为我们是人类,但对于计算机来说,告诉它如何去做是你的责任。
引用资料:
关于c - 什么会导致 OpenGL 中的多边形乱序渲染?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23731218/