2

I continue to work on shadow volumes in OpenGL, after finishing with volume itself, i need to draw a shadow using stencil buffer, and thats where i'm stuck :) I rendered this scene: http://prntscr.com/17lyr As you see, sphere represents light source, and one mushroom has its volume drawn directly to the screen, and one hasnt(i expect to see shadow instead). They are absolutely equal, made be translating one model some units on the X axis. Here is the code im working with:

 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);
}

Here is my GL initialization function:

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

And in my main function:

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

Is everything ok with my code? Because i dont see shadow and dont even know how to check if stencil values are set correctly.

Community
  • 1
  • 1
Anton
  • 3,006
  • 3
  • 26
  • 37
  • Where's the code where you acquire your OpenGL context? You might not be asking for a stencil buffer, and some systems might not give you one if you don't. – genpfault Nov 23 '10 at 16:30
  • Edited my question. I told both GL and GLUT to give me stencil buffer, why they still resist?) – Anton Nov 23 '10 at 16:45
  • 1
    Could this be because the second time you call `DrawDebugObject` you pass `false` as the value of `draw_sil` so `MarkSilouette` is not being called? – Jackson Pope Feb 15 '11 at 08:31

1 Answers1

0

There is no way to check stencils afaik. I am going to assume you are using depth fail. I recommend using glStencilOpSeperate like so.

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

Then when you draw the actual geometry make sure you are replacing stencil values like so:

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