繁体   English   中英

OpenGL 面部剔除无法正常工作

[英]OpenGL Face culling not working properly

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

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

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

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

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

我展示了效果的图像:在此处输入图片说明

灯光定义:

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

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

你,

  1. 要求足够分辨率的深度缓冲区? (类似于 32 位)
  2. 将 GL_DEPTH_BUFFER_BIT 传递给 gl_clear
  3. 尝试在近剪裁平面和远剪裁平面之间设置距离以获得更好的分辨率?

我知道你发布的关于你定义的对象与 glut 茶壶的部分,但 glut 茶壶肯定有一个 CCW 顶点绕组,所以当你打开剔除时它没有出现的事实让我想到了深度缓冲区。

简单的面剔除基于顶点的顺序 - 无论它们在屏幕空间中顺时针还是逆时针结束。 因此,问题可能出在顶点的定义顺序上,或者您可能正在应用某种转换,从而翻转顺序(例如,负缩放)。 法线仅在照明中起作用。

这个说法似乎很奇怪:

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

对此有两种可能的解释:

  1. 要么您的 GLUT 有问题,要么您(意外地?)交换了 Z 轴(例如,将所有负距离用于近剪裁平面和远剪裁平面)。

  2. 您切换了正面缠绕方向(调用glFrontFace

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

正面由屏幕空间顶点缠绕决定。 屏幕上的顶点按顺时针或逆时针顺序排列。 默认情况下,OpenGL 假定以逆时针顺序绘制顶点的面作为正面。 为此不考虑法线。

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

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

还要注意茶壶不是封闭的表面,剔除可以让你沿着盖子周围的缝隙看穿它。

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

天哪,我最近几天一直在为此工作,只是找到了解决方案。

显然!,您必须设置:

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 调用。 但我现在正在建造一个,如果有人感兴趣,我可能会在这几天发布它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM