C 什么会导致OpenGL中的多边形渲染混乱?

C 什么会导致OpenGL中的多边形渲染混乱?,c,opengl,glut,depth-buffer,culling,C,Opengl,Glut,Depth Buffer,Culling,我试图获得一些OpenGL的实际操作经验,所以我一直在编写一些基本程序。下面这个简短的程序是我第一次尝试渲染一个实体对象——一个旋转的立方体——但由于某种原因,一些背面的多边形似乎被正面的多边形所覆盖。我的问题是什么会导致这种情况?这和深度缓冲区有关吗?我发现,在这种情况下,启用面部剔除将隐藏效果,但为什么这是必要的呢?被较近的面遮挡的面不应该被隐藏吗 #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.

我试图获得一些OpenGL的实际操作经验,所以我一直在编写一些基本程序。下面这个简短的程序是我第一次尝试渲染一个实体对象——一个旋转的立方体——但由于某种原因,一些背面的多边形似乎被正面的多边形所覆盖。我的问题是什么会导致这种情况?这和深度缓冲区有关吗?我发现,在这种情况下,启用面部剔除将隐藏效果,但为什么这是必要的呢?被较近的面遮挡的面不应该被隐藏吗

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

typedef struct{
    int width;
    int height;
    char * title;
} window;
window win;

float theta = 0;
const float rotRate = 0.05;//complete rotations per second
int lastTime;

const float verts[][3] = {
    {0.0,0.0,0.0},
    {1.0,0.0,0.0},
    {0.0,1.0,0.0},
    {0.0,0.0,1.0},
    {0.0,1.0,1.0},
    {1.0,0.0,1.0},
    {1.0,1.0,0.0},
    {1.0,1.0,1.0}};

const int faceIndices[][4] = {
    {3,5,7,4},//front
    {1,0,2,6},//back
    {4,7,6,2},//top
    {0,1,5,3},//bottom
    {5,1,6,7},//right
    {0,3,4,2}};//left

void display(){
    //timing and rotation 
    int currentTime = glutGet(GLUT_ELAPSED_TIME);
    int dt = lastTime - currentTime;
    lastTime = currentTime;
    theta += (float)dt/1000.0*rotRate*360.0;
    if (theta > 360.0) theta += -360.0;

    //draw
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -5.0);
    glRotatef(theta, 0.0, 1.0, 0.0);
    glTranslatef(-1.0,-1.0,-1.0);
    glScalef(2.0, 2.0, 2.0);
    int f;
    for(f=0; f<6;f++){
        glBegin(GL_POLYGON);
        int v;
        for(v=0; v<4; v++){
            glColor3fv(verts[faceIndices[f][v]]);
            glVertex3fv(verts[faceIndices[f][v]]);
        }
        glEnd();
    }

    glutSwapBuffers();
}

void initializeGLUT(int * argc, char ** argv){
    glutInit(argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
    glutInitWindowSize(win.width, win.height);
    glutCreateWindow("OpenGL Cube");
    glutDisplayFunc(display);
    glutIdleFunc(display);
}

void initializeGL(){
    //Setup Viewport matrix
    glViewport(0,0,win.width, win.height);

    //Setup Projection matrix
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45,(float) win.width/win.height, 0.1, 100.0);

    //Initialize Modelview matrix
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    //Other
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClearDepth(1.0);
}

int main(int argc, char** argv){
    win.width = 640;
    win.height = 480;

    initializeGLUT(&argc, argv);
    initializeGL();

    glutMainLoop();

    return 0;
}
#包括
#包括
#包括
类型定义结构{
整数宽度;
内部高度;
字符*标题;
}窗口;
窗口赢;
浮点θ=0;
恒浮子旋转率=0.05//每秒完整旋转数
最后一次;
常量浮点顶点[][3]={
{0.0,0.0,0.0},
{1.0,0.0,0.0},
{0.0,1.0,0.0},
{0.0,0.0,1.0},
{0.0,1.0,1.0},
{1.0,0.0,1.0},
{1.0,1.0,0.0},
{1.0,1.0,1.0}};
const int faceindex[][4]={
{3,5,7,4},//前面
{1,0,2,6},//返回
{4,7,6,2},//顶部
{0,1,5,3},//底部
{5,1,6,7},//对
{0,3,4,2}};//左边
无效显示(){
//定时和旋转
int currentTime=glutGet(GLUT_运行时间);
int dt=上次时间-当前时间;
lastTime=当前时间;
θ+=(浮动)dt/1000.0*旋转率*360.0;
如果(θ>360.0)θ+=-360.0;
//画
glClear(GL_颜色_缓冲_位| GL_深度_缓冲_位);
glMatrixMode(GLU模型视图);
glLoadIdentity();
glTranslatef(0.0,0.0,-5.0);
glRotatef(θ,0.0,1.0,0.0);
glTranslatef(-1.0,-1.0,-1.0);
glScalef(2.0,2.0,2.0);
int f;
对于(f=0;f
这和深度缓冲区有关吗

是的,这是一个深度缓冲区问题,您在代码中启用了深度缓冲区,但显然您丢失了一些使用深度缓冲区的步骤

  • 通过调用glEnable(GL_depth_test)启用深度测试
  • 通过glDepthFunc设置深度测试功能,大多数情况下建议选择GL_LEQUAL,
    glDepthFunc(GL_LEQUAL);
    默认值为GL_LESS
  • 调用
    glClearDepth
    设置清除值,初始值为1.0,如果需要默认值,则此步骤不是强制性的
  • 绘制前不要忘记清除深度位,
    glClear(GL\u COLOR\u BUFFER\u bit | GL\u depth\u BUFFER\u bit);
  • 我发现,启用面剔除将隐藏这种效果 但为什么这是必要的呢

    默认情况下,OpenGL不会剔除任何面,推荐选项为

  • 按时钟顺序将顶点定义为背面(这也是OpenGL的选择)
  • 必要时剔除背面
  • 在本例中,您定义的多边形顶点都是按CCW顺序的,因此默认情况下它们都是正面,您只需要剔除背面以防止它们绘制,因此下面的代码也解决了您的问题

    glEnable(GL_CULL_FACE);
    glFrontFace(GL_CCW);
    glCullFace(GL_BACK);
    
    被较近的面遮挡的面不应该被隐藏吗 不管怎样

    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <GL/glut.h>
    
    typedef struct{
        int width;
        int height;
        char * title;
    } window;
    window win;
    
    float theta = 0;
    const float rotRate = 0.05;//complete rotations per second
    int lastTime;
    
    const float verts[][3] = {
        {0.0,0.0,0.0},
        {1.0,0.0,0.0},
        {0.0,1.0,0.0},
        {0.0,0.0,1.0},
        {0.0,1.0,1.0},
        {1.0,0.0,1.0},
        {1.0,1.0,0.0},
        {1.0,1.0,1.0}};
    
    const int faceIndices[][4] = {
        {3,5,7,4},//front
        {1,0,2,6},//back
        {4,7,6,2},//top
        {0,1,5,3},//bottom
        {5,1,6,7},//right
        {0,3,4,2}};//left
    
    void display(){
        //timing and rotation 
        int currentTime = glutGet(GLUT_ELAPSED_TIME);
        int dt = lastTime - currentTime;
        lastTime = currentTime;
        theta += (float)dt/1000.0*rotRate*360.0;
        if (theta > 360.0) theta += -360.0;
    
        //draw
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.0, 0.0, -5.0);
        glRotatef(theta, 0.0, 1.0, 0.0);
        glTranslatef(-1.0,-1.0,-1.0);
        glScalef(2.0, 2.0, 2.0);
        int f;
        for(f=0; f<6;f++){
            glBegin(GL_POLYGON);
            int v;
            for(v=0; v<4; v++){
                glColor3fv(verts[faceIndices[f][v]]);
                glVertex3fv(verts[faceIndices[f][v]]);
            }
            glEnd();
        }
    
        glutSwapBuffers();
    }
    
    void initializeGLUT(int * argc, char ** argv){
        glutInit(argc, argv);
        glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
        glutInitWindowSize(win.width, win.height);
        glutCreateWindow("OpenGL Cube");
        glutDisplayFunc(display);
        glutIdleFunc(display);
    }
    
    void initializeGL(){
        //Setup Viewport matrix
        glViewport(0,0,win.width, win.height);
    
        //Setup Projection matrix
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45,(float) win.width/win.height, 0.1, 100.0);
    
        //Initialize Modelview matrix
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    
        //Other
        glClearColor(0.0, 0.0, 0.0, 0.0);
        glClearDepth(1.0);
    }
    
    int main(int argc, char** argv){
        win.width = 640;
        win.height = 480;
    
        initializeGLUT(&argc, argv);
        initializeGL();
    
        glutMainLoop();
    
        return 0;
    }
    
    是的,这是有道理的,因为我们是人类,但对于计算机来说,你有责任告诉它如何做到这一点

    参考资料:

    这可以帮助您理解这个问题。因为OpenGL在moddels的正面和背面是不同的