2

我在屏幕上画了一个 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); 
4

5 回答 5

2

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

你,

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

我知道你发布的关于你定义的对象与过剩茶壶的部分,但过剩茶壶肯定有一个逆时针顶点缠绕,所以当你打开剔除时它没有出现的事实让我觉得深度缓冲区。

于 2012-05-02T20:44:51.147 回答
1

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

于 2012-05-02T11:17:10.180 回答
0

这种说法似乎很奇怪:

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

对此有两种可能的解释:

  1. 要么你的 GLUT 有问题,要么你(不小心?)交换了 Z 轴(例如,通过使用所有负距离作为近处和远处的剪裁平面)。

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

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

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

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

于 2012-05-02T13:00:50.903 回答
-1

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

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

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

于 2021-04-05T14:20:45.190 回答
-2

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

显然!,你必须设置:

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 亿这样的疯狂距离。

然后,除了一个晦涩的教程之外,我在任何地方都没有找到它,但是你必须设置你的 depthframebuffer(是的,另外 5 行就在那里)。

在生成帧缓冲区名称(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 调用。但是我现在正在建造一个,如果有人感兴趣,我可能会在这些日子里发布它。

于 2021-04-19T00:16:32.187 回答