[英]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);
你的深度缓冲看起来很糟糕。
你,
我知道你发布的关于你定义的对象与 glut 茶壶的部分,但 glut 茶壶肯定有一个 CCW 顶点绕组,所以当你打开剔除时它没有出现的事实让我想到了深度缓冲区。
简单的面剔除基于顶点的顺序 - 无论它们在屏幕空间中顺时针还是逆时针结束。 因此,问题可能出在顶点的定义顺序上,或者您可能正在应用某种转换,从而翻转顺序(例如,负缩放)。 法线仅在照明中起作用。
这个说法似乎很奇怪:
每当我激活 glEnable(GL_CULL_FACE) 时,每个对象都会得到不同的结果。 我可以正确显示立方体 (glCullFace(GL_BACK)) 或茶壶 (glCullFace(GL_FRONT)),但不能同时显示两者。
对此有两种可能的解释:
要么您的 GLUT 有问题,要么您(意外地?)交换了 Z 轴(例如,将所有负距离用于近剪裁平面和远剪裁平面)。
您切换了正面缠绕方向(调用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.