Wednesday, April 20, 2011

Final Stretch Update April 20

Hi guys,
So I made an attempt to do shadow volumes this week. At first I wanted the shadow volumes to be simple like extending some triangles to infinity to form cylinders to implement a kind of "drop shadow" which is sometimes implemented in multiplayer games as the "lowest" quality dynamic shadow rendering technique where FPS and performance is extremely important and gamers won't sacrifice quality if it drops their fps below say... 50 fps. Here's a pic of my cylinders to be used as shadow volumes, which change depending on the direction of the light.
After getting the volumes, I found a project that implemented shadow volumes and attempted to integrate the code to make it work. The code I scrapped together to draw the shadow volumes looked something like this...

void Terrain::DrawVolumes()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    glClearColor(sky_color[0], sky_color[1], sky_color[2], sky_color[3]);

    //Draw ambient
    glPushAttrib(GL_ENABLE_BIT);
    glEnable(GL_COLOR_MATERIAL);
    glLightfv(GL_LIGHT1, GL_POSITION, light_pos);
    glLightfv(GL_LIGHT1, GL_AMBIENT, sky_color_div);
    glLightfv(GL_LIGHT1, GL_DIFFUSE, sky_color_div);
    glLightfv(GL_LIGHT1, GL_SPECULAR, black);
    glEnable(GL_LIGHT1);
    glEnable(GL_LIGHTING);

    drawObjects() // terrain, static, and animateable

    //Draw shadow volumes
    glPushAttrib(GL_ALL_ATTRIB_BITS);
    glColorMask(0, 0, 0, 0);
    glShadeModel(GL_FLAT);
    glDepthMask(0);
    glDepthFunc(GL_LESS);
    glEnable(GL_STENCIL_TEST);

    glPushMatrix();
    glTranslatef(-half_width, 0, -half_height);

    // Shadow Volumes
        for(unsigned int i=0; i<1; i++)
        {
            //using zpass
            //Increment stencil buffer for front face depth pass
            glStencilFunc(GL_ALWAYS, 0, ~0);
            glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
            glCullFace(GL_BACK);

            // Draw Shadow Volume Objects
            DrawCylinders();

            //Decrement stencil buffer for back face depth pass
            glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
            glCullFace(GL_FRONT);

            // Draw Shadow Volume Objects
            DrawCylinders();
        }   
    glPopMatrix();
    glPopAttrib();

    //Now draw lit where stencil == 0
    glPushAttrib(GL_ENABLE_BIT);
    glEnable(GL_COLOR_MATERIAL);
    glLightfv(GL_LIGHT1, GL_POSITION, light_pos);
    glLightfv(GL_LIGHT1, GL_AMBIENT, sky_color_div);
    glLightfv(GL_LIGHT1, GL_DIFFUSE, sky_color);
    glLightfv(GL_LIGHT1, GL_SPECULAR, white);
    glEnable(GL_LIGHT1);
    glEnable(GL_LIGHTING);
    glStencilFunc(GL_EQUAL, 0, ~0);
    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
    glEnable(GL_STENCIL_TEST);

   drawObjects();
}

Unfortunately I wasn't getting any shadows, even after initializing openGL differently. I then thought, maybe drawing cylinders using gluQuadricObjects wasn't valid, so I drew a single triangle and extended its 3 edges to infinity by drawing 3 quads. I was able to see the 3 faces of this triangle without endcaps, but wasn't able to get a triangle of shadow.
I'm giving up on rendering shadow volumes for now, as I'd like to explore more shadow mapping techniques before the deadline for this project, which is next week. Although it's somewhat demoralizing to spend about 15 hours attempting to get shadow volumes working without much to show for the effort, I've learned that one of the biggest disadvantages to shadow volume rendering is implementation difficulty. Even had I been able to get the single triangle working, there's still several cases I hadn't handled like the viewport being inside a shadow volume, for example. Also the fps wasn't looking very promising even with drawing the cylinders, let alone extending silhouette edges for somewhat complicated 3d models. Stay tuned for the final!

1 comment:

  1. As we discussed, shadow volumes are sometimes a pain in practice. Let us know how your shadow mapping implementations turn out.

    ReplyDelete