Какво може да доведе до изобразяване на полигони в OpenGL неправилно?

Опитвам се да придобия малко практически опит с 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;
}

person AIGuy110    schedule 19.05.2014    source източник
comment
stackoverflow.com/a/18922286/2003898 Това може да ви помогне да разберете проблема. Тъй като OpenGL се различава между предната и задната страна на моделите   -  person dhein    schedule 19.05.2014


Отговори (1)


Има ли нещо общо с буфера за дълбочина?

Да, това е проблем с буфера за дълбочина, вие сте активирали буфера за дълбочина във вашия код, но очевидно сте изгубили някои стъпки, за да използвате буфера за дълбочина

  1. Активирайте теста за дълбочина, като извикате glEnable(GL_DEPTH_TEST)
  2. Задайте функцията за тестване на дълбочина от glDepthFunc, GL_LEQUAL е препоръчителният избор за повечето случаи, glDepthFunc(GL_LEQUAL); стойността по подразбиране е GL_LESS.
  3. Извикайте glClearDepth, за да зададете изчистената стойност, първоначалната стойност е 1,0, тази стъпка не е задължителна, ако искате стойността по подразбиране.
  4. Не забравяйте да изчистите битовете за дълбочина, преди да рисувате, glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Открих, че активирането на премахване на лица ще скрие ефекта в този случай, но защо трябва да е необходимо?

По подразбиране OpenGL не изтрива лице, препоръчаната опция е

  1. Дефинирайте върховете в реда на часовника като задна страна (това също е избор на OpenGL)
  2. Отстранете лицата, когато е необходимо.

Във вашия случай вие сте дефинирали върховете на полигона всички в CCW ред, така че всички те са предни лица по подразбиране, просто трябва да извадите задните лица, за да им попречите да рисуват, така че следният код също решава проблема ви.

glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glCullFace(GL_BACK);

Не трябва ли лице, което е затворено от по-близко лице, да бъде скрито независимо от това?

Да, това има смисъл, тъй като ние сме човешки същества, но за компютъра е ваша отговорност да му кажете как да направи това.

Препратки:

Буфер за дълбочина

Отрязване на лица

person zdd    schedule 19.05.2014