Hello everyone,
I have been working on implementing simple shadow mapping in OpenGL, the old way - no FBOs, most calculations are done in CPU but the problem is that I believe alpha test always passes.
I used a couple different source codes online and to make sure that the objects are not clipped from the light perspective and to avoid precision issues, I used the same numbers as in one of the working examples (scale of objects, far-near clipping planes) but still I cannot get any shadows at all.
In the process, I first render into depth texture, then render the scene using a single shader with fragment values darkened (simulating ambient light), then render the same scene using the pixel colors as they are. Below is the source code of the renderer. I tested dark and light passes separately and they are working correctly so the result is a scene fully lit.
I would appreciate it if anyone could help me on this.
Thanks,
Initializations
bool
Renderer::initialize()
{
glEnable( GL_TEXTURE_2D );
glEnable( GL_DEPTH_TEST );
glEnable( GL_CULL_FACE );
glCullFace( GL_BACK );
glClearColor( 0.0, 0.0, 0.0, 1.f );
_initializeApplicationSpecific();
return true;
}
void
Renderer::_initializeApplicationSpecific()
{
lightPosition_ = Vec4D( 2.f, 3.f, -2.f );
lightTarget_ = Vec4D( 0.f, 0.f, 0.f );
//Calculate light view and projection matrices
glPushMatrix();
//Light matrices
glLoadIdentity();
gluPerspective( 45.0f, 1.0f, 2.0f, 8.0f );
glGetFloatv( GL_MODELVIEW_MATRIX, reinterpret_cast<float*>( &lightProjMatrix_ ) );
glLoadIdentity();
gluLookAt( lightPosition_.x, lightPosition_.y, lightPosition_.z, lightTarget_.x, lightTarget_.y, lightTarget_.z, 0.f, 1.f, 0.f );
glGetFloatv( GL_MODELVIEW_MATRIX, reinterpret_cast<float*>( &lightViewMatrix_ ) );
glPopMatrix();
glGenTextures( 1, &depthTexture_ );
glBindTexture( GL_TEXTURE_2D, depthTexture_ );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY );
glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, DEPTH_TEXTURE_WIDTH, DEPTH_TEXTURE_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
glClearDepth( 1.0f );
glDepthFunc( GL_LEQUAL );
biasMatrix_ = Mat44( Vec4D( 0.5, 0, 0, 0.5 ),
Vec4D( 0.0, 0.5, 0, 0.5 ),
Vec4D( 0, 0, 0.5, 0.5 ),
Vec4D( 0, 0, 0, 1 ) );
}
Main draw loop
void
Renderer::draw()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
_drawToDepthTexture();
glClear( GL_DEPTH_BUFFER_BIT );
_drawScene( RG_DARK ); //Ambient pass
_drawLightPass(); //Light pass
glutSwapBuffers();
glutPostRedisplay();
}
Rendering to depth texture from light’s perspective
void
Renderer::_drawToDepthTexture()
{
glViewport( 0, 0, DEPTH_TEXTURE_WIDTH, DEPTH_TEXTURE_HEIGHT );
glCullFace( GL_FRONT );
glColorMask( 0, 0, 0, 0 );
glMatrixMode( GL_PROJECTION_MATRIX );
glPushMatrix();
glLoadMatrixf( reinterpret_cast<float*>( &lightProjMatrix_ ) );
glMatrixMode( GL_MODELVIEW_MATRIX );
glPushMatrix();
glLoadMatrixf( reinterpret_cast<float*>( &lightViewMatrix_ ) );
_drawScene( RG_ALL );
glBindTexture( GL_TEXTURE0, depthTexture_ );
glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, DEPTH_TEXTURE_WIDTH, DEPTH_TEXTURE_HEIGHT );
glMatrixMode( GL_PROJECTION_MATRIX );
glPopMatrix();
glMatrixMode( GL_MODELVIEW_MATRIX );
glPopMatrix();
glColorMask( 1, 1, 1, 1 );
glCullFace( GL_BACK );
Vec2D winSize = SystemManager::getInstance().getGlutManager()->getWindowSize();
glViewport( 0, 0, winSize.x, winSize.y );
}
Final comparison pass
void
Renderer::_drawLightPass()
{
Mat44 texMatrix = biasMatrix_ * lightProjMatrix_ * lightViewMatrix_;
glEnable( GL_TEXTURE_GEN_S );
glEnable( GL_TEXTURE_GEN_T );
glEnable( GL_TEXTURE_GEN_R );
glEnable( GL_TEXTURE_GEN_Q );
Vec4D r1 = texMatrix.getRow( 1 );
Vec4D r2 = texMatrix.getRow( 2 );
Vec4D r3 = texMatrix.getRow( 3 );
Vec4D r4 = texMatrix.getRow( 4 );
glBindTexture( GL_TEXTURE_2D, depthTexture_ );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL );
glTexParameteri( GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY );
//Set alpha test to discard false comparisons
glAlphaFunc( GL_GEQUAL, 0.99f );
glEnable( GL_ALPHA_TEST );
_drawScene( RG_LIT );
glDisable( GL_TEXTURE_GEN_S );
glDisable( GL_TEXTURE_GEN_T );
glDisable( GL_TEXTURE_GEN_R );
glDisable( GL_TEXTURE_GEN_Q );
glDisable( GL_ALPHA_TEST );
}