简体   繁体   English

OpenGL 面部剔除无法正常工作

[英]OpenGL Face culling not working properly

I draw a glutSolidCube and a glutSolidTeapot on the screen.我在屏幕上绘制了一个 glutSolidCube 和一个 glutSolidTeapot。

Whenever I activate glEnable(GL_CULL_FACE) I get different results for each object.每当我激活 glEnable(GL_CULL_FACE) 时,每个对象都会得到不同的结果。 I can either get the cube to be shown properly (glCullFace(GL_BACK)), or the teapot (glCullFace(GL_FRONT)), but never both of them.我可以正确显示立方体 (glCullFace(GL_BACK)) 或茶壶 (glCullFace(GL_FRONT)),但不能同时显示两者。

If I disable culling, then both of them are shown properly, but I would like to be able to activate it.如果我禁用剔除,那么它们都会正确显示,但我希望能够激活它。

Other objects defined by me are not being shown properly either.我定义的其他对象也没有正确显示。

Since these objets are defined in GLUT I can guess it's not a problem of their normals, or is it?由于这些对象是在 GLUT 中定义的,我可以猜测这不是它们的法线问题,或者是吗?

I show an image of the effect:我展示了效果的图像:在此处输入图片说明

Light definition:灯光定义:

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
    }

Depth test and culling enabling:深度测试和剔除启用:

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

Your depth buffering looks bad.你的深度缓冲看起来很糟糕。

Do you,你,

  1. ask for a depth buffer of adequate resolution?要求足够分辨率的深度缓冲区? (something like 32 bits) (类似于 32 位)
  2. pass in GL_DEPTH_BUFFER_BIT to gl_clear将 GL_DEPTH_BUFFER_BIT 传递给 gl_clear
  3. tried making the distance between your near and far clipping planes to get better resolution?尝试在近剪裁平面和远剪裁平面之间设置距离以获得更好的分辨率?

I know the part you posted about your defined object vs the glut teapot, but the glut teapot is for sure has a CCW vertex winding, so the fact that it doesn't show up when you turn on culling makes me think depth buffer.我知道你发布的关于你定义的对象与 glut 茶壶的部分,但 glut 茶壶肯定有一个 CCW 顶点绕组,所以当你打开剔除时它没有出现的事实让我想到了深度缓冲区。

Simple face culling is based on the order of the vertices - whether they end up clockwise in screen space or anti-clockwise.简单的面剔除基于顶点的顺序 - 无论它们在屏幕空间中顺时针还是逆时针结束。 So, the problem could be in the definition order of the vertices, or you might be applying some kind of transform, which flips the order (eg. negative scaling).因此,问题可能出在顶点的定义顺序上,或者您可能正在应用某种转换,从而翻转顺序(例如,负缩放)。 The normals only play a role in lighting.法线仅在照明中起作用。

This statement seems odd:这个说法似乎很奇怪:

Whenever I activate glEnable(GL_CULL_FACE) I get different results for each object.每当我激活 glEnable(GL_CULL_FACE) 时,每个对象都会得到不同的结果。 I can either get the cube to be shown properly (glCullFace(GL_BACK)), or the teapot (glCullFace(GL_FRONT)), but never both of them.我可以正确显示立方体 (glCullFace(GL_BACK)) 或茶壶 (glCullFace(GL_FRONT)),但不能同时显示两者。

There are two possible explanations for this:对此有两种可能的解释:

  1. Either your GLUT is buggy, or you've (accidently?) swapped the Z axis (for example by using all negative distances for near and far clipping plane).要么您的 GLUT 有问题,要么您(意外地?)交换了 Z 轴(例如,将所有负距离用于近剪裁平面和远剪裁平面)。

  2. You switched the front face winding direction (call to glFrontFace )您切换了正面缠绕方向(调用glFrontFace

Other objects defined by me are not being shown properly either.我定义的其他对象也没有正确显示。

The front face is determined by screen space vertex winding.正面由屏幕空间顶点缠绕决定。 The vertices order on screen in either clockwise or counterclockwise.屏幕上的顶点按顺时针或逆时针顺序排列。 By default OpenGL assumes faces which are drawn with their vertices in counterclockwise order as front face.默认情况下,OpenGL 假定以逆时针顺序绘制顶点的面作为正面。 Normals are not took into account for this.为此不考虑法线。

I think the easiest way for you to fix this is by swapping the order in which you submit the vertices.我认为解决此问题的最简单方法是交换提交顶点的顺序。

I think the GLUT teapot only renders correctly without CULL_FACE enabled, which would indicate that the normals that are generated don't correspond to the vertex order.我认为 GLUT 茶壶只能在没有启用 CULL_FACE 的情况下正确渲染,这表明生成的法线与顶点顺序不对应。 The visual effect of this is that the teapot seems to rotate in the opposite direction as other objects.这样做的视觉效果是茶壶似乎与其他物体以相反的方向旋转。 This is the well-known effect of rotating a hollow mask.这就是众所周知的旋转空心面罩的效果。 The brain tries to make sense of the scene taking its cues from the lighting.大脑试图从灯光中获取线索来理解场景。 If I invert the space by a glScalef(-1,-1,-1) before drawing, it looks like a normal teapot, even when culling.如果我在绘制之前通过 glScalef(-1,-1,-1) 反转空间,它看起来就像一个普通的茶壶,即使在剔除时也是如此。

Also note the teapot is not a closed surface, and that culling allows you to see through it along the gap around the lid.还要注意茶壶不是封闭的表面,剔除可以让你沿着盖子周围的缝隙看穿它。

If you want to combine 'cullable' objects next to this uncullable teapot, you can switch off culling just when rendering the teapot.如果你想在这个不可剔除的茶壶旁边组合“剔除”对象,你可以在渲染茶壶时关闭剔除。

OMG, I have been working for the last days on this and just find that solution.天哪,我最近几天一直在为此工作,只是找到了解决方案。

Obviously!, you have to set :显然!,您必须设置:

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.

Also, make sure your camera is not at crazy distances like 0.0000001f to 1 Billions.另外,请确保您的相机不在像 0.0000001f 到 10 亿的疯狂距离。

Then, I didnt find it anywhere except into an obscur tutorial, but you have to set you depthframebuffer (yep, another 5 lines right there).然后,除了一个晦涩的教程之外,我没有在任何地方找到它,但是您必须设置深度帧缓冲区(是的,还有另外 5 行)。

Shuve these 5 lines anywhere after you generate a framebuffername ( glGenFramebuffers(1, &FramebufferName);) and before your display/loop and that WILL do the trick.在生成 framebuffername ( glGenFramebuffers(1, &FramebufferName);) 之后和显示/循环之前,将这 5 行放在任何地方,这样就可以了。 I tried it before the FramebufferName generation and it didnt work.我在 FramebufferName 生成之前尝试过它,但它没有用。 But before or after textures generation and it still does work.但是在纹理生成之前或之后,它仍然有效。

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

This openGL really did drive me crazy with years and I still cant find a complete higher c++ library that englobes every opengl calls.多年来,这个 openGL 确实让我发疯了,但我仍然找不到一个完整的高级 C++ 库来包含每个 opengl 调用。 But im building one right now and if anyone is interrested, I might publish it one of these days.但我现在正在建造一个,如果有人感兴趣,我可能会在这几天发布它。

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

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