Original Post
I've been trying to implement shadow mapping using Cg shaders for a while now, but I can't seem to get it right. I've been hung up on actually capturing the depth buffer to use as my shadow map. I figured the complexity of my original program was causing too much trouble with debugging, so I set out to create a simple test bed program (why I didn't do this from the start, I don't know). All this program _should_ do, is alternate between rendering the scene normally, and rendering the scene to a FBO with a depth attachment (toggle by pressing F1). When using the FBO, the depth attachment is then rendered to the screen...only problem is this last part comes out as a black screen. I've been looking at this code for too long now to figure out what's wrong with it - I don't understand FBOs well enough to begin with, was hoping I could figure them out while working on this. Could someone please look through my code below and tell me what exactly it is that I'm doing wrong? EDIT: Tagged the source code the wrong way.
void initFBO(void)
{
glGenTextures(1, &shadow_tx);
glBindTexture(GL_TEXTURE_2D, shadow_tx);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16,
shadow_sz, shadow_sz, 0, GL_DEPTH_COMPONENT,
GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// create fbo and attach texture to ti
glGenFramebuffersEXT(1, &shadow_fb);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shadow_fb);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_TEXTURE_2D, shadow_tx, 0);
glDrawBuffer(GL_FALSE);
glReadBuffer(GL_FALSE);
// verify all is well and restore state
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
switch (status)
{
case GL_FRAMEBUFFER_COMPLETE_EXT:
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
cerr << "FBO configuration unsupported" << endl;
exit(-1);
default:
cerr << "FBO programmer error" << endl;
exit(-1);
}
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
}// end initFBO()
void renderShadowMap(void)
{
glDisable(GL_LIGHTING);
glPushAttrib(GL_VIEWPORT);
glViewport(0, 0, shadow_sz, shadow_sz);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(-1, 1, -1, 1);
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, shadow_tx);
glBegin( GL_QUADS );
{
glTexCoord2f( 0.0f, 0.0f );
glVertex3f( -1.0f, -1.0f, 0.0f );
glTexCoord2f( 0.0f, 1.0f );
glVertex3f( -1.0f, 1.0f, 0.0f );
glTexCoord2f( 1.0f, 1.0f );
glVertex3f( 1.0f, 1.0f, 0.0f );
glTexCoord2f( 1.0f, 0.0f );
glVertex3f( 1.0f, -1.0f, 0.0f );
}
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glPopMatrix();
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopAttrib();
glEnable(GL_LIGHTING);
}// end renderShadowMap()
void renderScene(void)
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
{
glTranslatef( 0.0f, 2.5f, 0.0f );
glRotatef(-g_fSpinY_R, 1.0f, 0.0f, 0.0f);
glRotatef(g_fSpinX_R, 0.0f, 1.0f, 0.0f);
glColor3f( 1.0f, 1.0f ,1.0f );
glutSolidTeapot(1.0);
}
glPopMatrix();
glPushMatrix();
{
glRotatef(-g_fSpinX_R, 0.0f, 1.0f, 0.0f);
glBegin( GL_QUADS );
{
glNormal3f( 0.0f, 1.0f, 0.0f );
glVertex3f(-5.0f, 0.0f, -5.0f );
glVertex3f(-5.0f, 0.0f, 5.0f );
glVertex3f( 5.0f, 0.0f, 5.0f );
glVertex3f( 5.0f, 0.0f, -5.0f );
}
glEnd();
}
glPopMatrix();
}// end renderScene()
void render(void)
{
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt(g_lightPosition[0],
g_lightPosition[1],
g_lightPosition[2],
0.0f, 2.5f, 0.0f,
0.0f, 1.0f, 0.0f);
// Get the model-view matrix
glGetFloatv(GL_MODELVIEW_MATRIX, g_lightsLookAtMatrix);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, -2.0f, -15.0f);
glRotatef(-g_fSpinY_L, 1.0f, 0.0f, 0.0f);
glRotatef(-g_fSpinX_L, 0.0f, 1.0f, 0.0f);
// Render the light's position as a sphere...
glDisable(GL_LIGHTING);
glPushMatrix();
{
glLightfv(GL_LIGHT0, GL_POSITION, g_lightPosition);
glTranslatef(g_lightPosition[0], g_lightPosition[1], g_lightPosition[2]);
glColor3f(1.0f, 1.0f, 0.5f);
glutSolidSphere(0.1, 8, 8);
}
glPopMatrix();
glEnable(GL_LIGHTING);
if(g_bRenderDepthTexture)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, shadow_tx);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shadow_fb);
}
renderScene();
if(g_bRenderDepthTexture)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}
if(g_bRenderDepthTexture)
renderShadowMap();
glutSwapBuffers();
}// end render()