OpenGL Face剔除无法正常工作

时间:2012-05-02 11:11:37

标签: opengl

我在屏幕上绘制了一个glutSolidCube和一个glutSolidTeapot。

每当我激活glEnable(GL_CULL_FACE)时,我会为每个对象获得不同的结果。我可以正确显示立方体(glCullFace(GL_BACK)),或茶壶(glCullFace(GL_FRONT)),但不能同时显示它们。

如果我禁用剔除,那么它们都会正确显示,但我希望能够激活它。

我定义的其他对象也没有正确显示。

由于这些objets是在GLUT中定义的,我可以猜测这不是他们法线的问题,或者是它?

我展示了效果的图像: enter image description here

光线定义:

void setLighting(void) {

//setMaterial();
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);

//ambient light color variables
GLfloat alr = 0.0;
GLfloat alg = 0.0;
GLfloat alb = 0.0;

//diffuse light color variables
GLfloat dlr = 1.0;
GLfloat dlg = 1.0;
GLfloat dlb = 1.0;

//specular light color variables
GLfloat slr = 1.0;
GLfloat slg = 1.0;
GLfloat slb = 1.0;


//light position variables
GLfloat lx = 0.0;
GLfloat ly = 100.0;
GLfloat lz = 100.0;
GLfloat lw = 0.0;


GLfloat DiffuseLight[]  = {dlr, dlg, dlb}; //set DiffuseLight[] to the specified values
GLfloat AmbientLight[]  = {alr, alg, alb}; //set AmbientLight[] to the specified values
GLfloat SpecularLight[] = {slr, slg, slb}; //set AmbientLight[] to the specified values
GLfloat LightPosition[] = {lx, ly, lz, lw}; //set the LightPosition to the specified values



GLfloat global_ambient[] = { 0.1f, 0.1f, 0.1f, 1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
glEnable(GL_LIGHTING);

glLightfv (GL_LIGHT0, GL_DIFFUSE,   DiffuseLight); //change the light accordingly
glLightfv (GL_LIGHT0, GL_AMBIENT,   AmbientLight); //change the light accordingly
glLightfv (GL_LIGHT0, GL_SPECULAR,  SpecularLight); //change the light accordingly

glLightfv (GL_LIGHT0, GL_POSITION,  LightPosition); //change the light accordingly
    }

深度测试和剔除启用:

    glEnable(GL_DEPTH_TEST);    // Enable the depth buffer
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Ask for nicest perspective correction

glEnable(GL_CULL_FACE);     // Cull back facing polygons
    glCullFace(GL_BACK); 

5 个答案:

答案 0 :(得分:2)

你的深度缓冲看起来很糟糕。

你呢,

  1. 要求足够分辨率的深度缓冲区? (像32位一样)
  2. 将GL_DEPTH_BUFFER_BIT传递给gl_clear
  3. 尝试在近剪裁平面和远剪裁平面之间建立距离以获得更好的分辨率?
  4. 我知道你发布的关于你定义的物体的部分与过剩的茶壶相比,但是过剩的茶壶确实有一个CCW顶点缠绕,所以当你打开剔除时它没有出现这一事实让我深入思考缓冲液中。

答案 1 :(得分:1)

简单的面部剔除基于顶点的顺序 - 无论它们是在屏幕空间中顺时针方向还是逆时针方向。因此,问题可能在于顶点的定义顺序,或者您可能正在应用某种类型的变换,这会颠倒顺序(例如,负缩放)。法线只在照明中发挥作用。

答案 2 :(得分:1)

这句话似乎很奇怪:

  

每当我激活glEnable(GL_CULL_FACE)时,我会为每个对象获得不同的结果。我可以正确显示立方体(glCullFace(GL_BACK)),或茶壶(glCullFace(GL_FRONT)),但不能同时显示它们。

对此有两种可能的解释:

  1. 您的GLUT是否有缺陷,或者您(意外地?)交换了Z轴(例如,通过使用近和远裁剪平面的所有负距离)。

  2. 您切换了正面缠绕方向(致电glFrontFace

  3.   

    我定义的其他对象也没有正确显示。

    正面由屏幕空间顶点绕组确定。顶点顺时针或逆时针在屏幕上排序。默认情况下,OpenGL假定以顶点逆时针方向绘制的面作为正面。不考虑法线。

    我认为解决此问题的最简单方法是交换提交顶点的顺序。

答案 3 :(得分:-1)

我认为 GLUT 茶壶只有在没有启用 CULL_FACE 的情况下才能正确渲染,这表明生成的法线与顶点顺序不对应。这样做的视觉效果是茶壶似乎与其他物体以相反的方向旋转。这就是众所周知的旋转空心面罩的效果。大脑试图从灯光中获取线索来理解场景。如果我在绘制之前通过 glScalef(-1,-1,-1) 反转空间,它看起来就像一个普通的茶壶,即使在剔除时也是如此。

另请注意,茶壶不是封闭的表面,通过剔除,您可以沿着盖子周围的缝隙看穿它。

如果你想在这个不可剔除的茶壶旁边组合“剔除”对象,你可以在渲染茶壶时关闭剔除。

答案 4 :(得分:-2)

天哪,我最近几天一直在研究这个,只是找到了解决方案。

显然!,您必须设置:

glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);     //    Don't waste energy trying the glCullFace(GL_BACK);  
                            //    thing since its set at GL_BACK by default.
                            //    Yes, it does cuts triangle NOT facing you.

另外,请确保您的相机不在像 0.0000001f 到 10 亿的疯狂距离。

然后,除了一个晦涩的教程之外,我没有在任何地方找到它,但是您必须设置深度帧缓冲区(是的,还有另外 5 行)。

在生成 framebuffername ( glGenFramebuffers(1, &FramebufferName);) 之后和显示/循环之前,将这 5 行放在任何地方,这样就可以了。我在 FramebufferName 生成之前尝试过它,但它没有用。但是在纹理生成之前或之后,它仍然有效。

// The depth buffer
GLuint depthrenderbuffer = 0;
glGenRenderbuffers(1, &depthrenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, windowWidth, windowHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbuffer);

多年来,这个 openGL 确实让我发疯,但我仍然找不到一个完整的高级 C++ 库,它包含每个 opengl 调用。但我现在正在构建一个,如果有人感兴趣,我可能会在这几天发布它。