简体   繁体   中英

OpenGL Face culling not working properly

I draw a glutSolidCube and a glutSolidTeapot on the screen.

Whenever I activate glEnable(GL_CULL_FACE) I get different results for each object. I can either get the cube to be shown properly (glCullFace(GL_BACK)), or the teapot (glCullFace(GL_FRONT)), but never both of them.

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?

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)
  2. pass in GL_DEPTH_BUFFER_BIT to 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.

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. I can either get the cube to be shown properly (glCullFace(GL_BACK)), or the teapot (glCullFace(GL_FRONT)), but never both of them.

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

  2. You switched the front face winding direction (call to 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. 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. 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.

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.

Then, I didnt find it anywhere except into an obscur tutorial, but you have to set you depthframebuffer (yep, another 5 lines right there).

Shuve these 5 lines anywhere after you generate a framebuffername ( glGenFramebuffers(1, &FramebufferName);) and before your display/loop and that WILL do the trick. I tried it before the FramebufferName generation and it didnt work. 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. But im building one right now and if anyone is interrested, I might publish it one of these days.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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