Объемы теней - финальная стадия - PullRequest
2 голосов
/ 23 ноября 2010

Я продолжаю работать с теневыми томами в OpenGL, после заканчивая самим томом , мне нужно нарисовать тень, используя буфер трафарета, и вот где я застрял :) Я отрисовал эту сцену: http://prntscr.com/17lyr Как вы видите, сфера представляет источник света, а у одного гриба его объем обращен непосредственно к экрану, а у другого нет (я ожидаю увидеть вместо этого тень).Они абсолютно одинаковы, переводят одну модель в несколько единиц по оси X.Вот код, с которым я работаю:

 void Display(){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    glLoadIdentity();
    glLightfv(GL_LIGHT1,GL_POSITION,light_position[0]);

    cam.SetPrespective();

    DrawDebugObject(true);
    glTranslatef(15,0,0);
    DrawDebugObject(false);

    glFinish();
    glutSwapBuffers();
}

void DrawDebugObject(bool draw_sil){
    glPushMatrix();
    glTranslatef(light_position[1][0],light_position[1][1],light_position[1][2]);
    glColor3ub(255,255,0);
    gluSphere(gluNewQuadric(),0.5,10,10);
    glPopMatrix();

    glDisable(GL_LIGHTING);
    glBegin(GL_QUADS);
        glColor3f(1,1,1);
        glVertex3f(-100,0,-100);
        glVertex3f(-100,0,100);
        glVertex3f(100,0,100);
        glVertex3f(100,0,-100);
        glEnd();
    glEnable(GL_LIGHTING);
    pModel->draw();
    if(draw_sil)
        pModel->markSilouette(light_position[1]);
    castShadow(pModel,light_position[1]);   
}

void castShadow(Model* model,float* lp){
        glDisable(GL_LIGHTING);
        glDepthMask(GL_FALSE);
        glDepthFunc(GL_LEQUAL);

        pModel->markVisible(lp);

        glEnable(GL_STENCIL_TEST);
        glColorMask(0, 0, 0, 0);
        glStencilFunc(GL_ALWAYS, 1, 0xffffffff);

        // first pass, stencil operation decreases stencil value
        glFrontFace(GL_CCW);
        glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
        pModel->markSilouette(lp);

        // second pass, stencil operation increases stencil value
        glFrontFace(GL_CW);
        glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
        pModel->markSilouette(lp);

        glFrontFace(GL_CCW);
        glColorMask(1, 1, 1, 1);

        //draw a shadowing rectangle covering the entire screen
        glColor4f(1.0f, 0.0f, 0.0f, 0.4f);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glStencilFunc(GL_NOTEQUAL, 0, 0xffffffff);
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
        glPushMatrix();
        glLoadIdentity();
        glBegin(GL_QUADS);
        glVertex3f(-0.1f, 0.1f,-0.10f);
        glVertex3f(-0.1f,-0.1f,-0.10f);
        glVertex3f( 0.1f, 0.1f,-0.10f);
        glVertex3f( 0.1f,-0.1f,-0.10f);
        glEnd();
        glPopMatrix();
        glDisable(GL_BLEND);

        glDepthFunc(GL_LEQUAL);
        glDepthMask(GL_TRUE);
        glEnable(GL_LIGHTING);
        glDisable(GL_STENCIL_TEST);
}

Вот моя функция инициализации GL:

void InitGL(){
    glEnable(GL_NORMALIZE);
    glEnable(GL_LIGHTING);
    glEnable(GL_TEXTURE_2D);
    glShadeModel(GL_SMOOTH);
    glClearDepth(1.0f);                                 // Depth Buffer Setup
    glClearStencil(0);                                  // Stencil Buffer Setup
    glEnable(GL_DEPTH_TEST);                            // Enables Depth Testing
    glDepthFunc(GL_LEQUAL);                             // The Type Of Depth Testing To Do

    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // Really Nice Perspective Calculations
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
    glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
    glHint(GL_FOG_HINT, GL_NICEST);
...nothing important after that

И в моей основной функции:

glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE|GLUT_STENCIL|GLUT_ACCUM);
    glutInitWindowSize(Width,Height);
    glutCreateWindow("Spheres");

    glutDisplayFunc(Display);
    glutReshapeFunc(Reshape);
    glutKeyboardFunc(Keyboard);
    glutKeyboardUpFunc(KeyboardUp);
    glutTimerFunc(TIMEOUT,Timer,TIMEOUT);
    glutPassiveMotionFunc(MouseMove);

Это всехорошо с моим кодом?Потому что я не вижу тени и даже не знаю, как проверить, правильно ли установлены значения трафарета.

1 Ответ

0 голосов
/ 15 апреля 2011

Нет способа проверить трафареты на афаике.Я собираюсь предположить, что вы используете провал глубины.Я рекомендую использовать glStencilOpSeperate следующим образом.

    glClear(GL_STENCIL_BUFFER_BIT);
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    glEnable(GL_STENCIL_TEST);
    glEnable(GL_POLYGON_OFFSET_FILL);
    glDisable(GL_CULL_FACE);
    glStencilFunc(GL_ALWAYS, 0x00, 0xFF);
    glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP);
    glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP);
    glPolygonOffset(0.0f, 5.0f);
    glDepthFunc(GL_LESS);

Затем, когда вы рисуете фактическую геометрию, убедитесь, что вы заменяете значения трафарета следующим образом:

    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    glEnable(GL_CULL_FACE);
    glDisable(GL_POLYGON_OFFSET_FILL);
    glCullFace(GL_BACK);
    glDepthFunc(GL_GEQUAL);
    glStencilFunc(GL_EQUAL, 0x00, 0xFF);
    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
...