I’m tearing my hair out with this one. I’m trying to do basic shadow mapping, and if I don’t use a shader I get this correct result:
When I use my shader instead, I get this:
Does this look familiar to anyone? I’m not using FBO/pixelbuffers, just a simple copytex. Here’s my texture creation:
glGenTextures( 1, &g_ShadmapID );
glBindTexture( GL_TEXTURE_2D, g_ShadmapID );
glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, g_ShadmapSize, g_ShadmapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL );
Here’s how I render the shadow:
// first, we render the scene from the light's point of view
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
// Orient the view to look from the light to the center of the scene
gluLookAt( g_LightPos[0],g_LightPos[1],g_LightPos[2], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f );
// save the light's viewmatrix
glGetFloatv(GL_MODELVIEW_MATRIX, g_LightViewMatrix);
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// offset the drawing to help stop z-fighting - the values need to be tweaked for
// specific scenes
glPolygonOffset( 4.0f, 8.0f );
glEnable( GL_POLYGON_OFFSET_FILL );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
// prepare the view - note that the view angle should be 45deg, and the viewport
// is set to the dimensions of the shadow map
gluPerspective( 45.0f, (float)g_ScreenWidth / (float)g_ScreenHeight, 0.1f, 100.0f );
glViewport( 0, 0, g_ShadmapSize, g_ShadmapSize );
// re-orient the view for the light
glMatrixMode( GL_MODELVIEW );
glMultMatrixf( g_LightViewMatrix );
// render the scene itself
glColorMask(0, 0, 0, 0);
RenderWorld();
glColorMask(1, 1, 1, 1);
glDisable( GL_POLYGON_OFFSET_FILL );
// ..and copy it to texture
glBindTexture( GL_TEXTURE_2D, g_ShadmapID );
glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, g_ShadmapSize, g_ShadmapSize );
Here’s how I render the scene afterwards:
// we're done rendering from the light's viewpoint
// now render to screen
glClearColor( 0.0f, 0.0f, 1.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
// view from camera
gluLookAt( g_CameraPos[0], g_CameraPos[1], g_CameraPos[2], g_CameraTarget[0], g_CameraTarget[1], g_CameraTarget[2], 0.0f, 1.0f, 0.0f );
// position the light
glLightfv( GL_LIGHT0, GL_POSITION, g_LightPos );
// setup GL to generate the correct texture matrix - should not be
// needed when workig with the shader
float x[] = { 1.0f, 0.0f, 0.0f, 0.0f };
float y[] = { 0.0f, 1.0f, 0.0f, 0.0f };
float z[] = { 0.0f, 0.0f, 1.0f, 0.0f };
float w[] = { 0.0f, 0.0f, 0.0f, 1.0f };
glTexGenfv( GL_S, GL_EYE_PLANE, x );
glTexGenfv( GL_T, GL_EYE_PLANE, y );
glTexGenfv( GL_R, GL_EYE_PLANE, z );
glTexGenfv( GL_Q, GL_EYE_PLANE, w );
glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
glEnable( GL_TEXTURE_GEN_S );
glEnable( GL_TEXTURE_GEN_T );
glEnable( GL_TEXTURE_GEN_R );
glEnable( GL_TEXTURE_GEN_Q );
// add an offset and bias here when setting up the viewport
glMatrixMode( GL_TEXTURE );
glLoadIdentity();
glTranslatef( 0.5f, 0.5f, 0.5f );
glScalef( 0.5f, 0.5f, 0.5f );
gluPerspective( 45.0f, (float)g_ScreenWidth / (float)g_ScreenHeight, 0.1f, 100.0f);
glMultMatrixf( g_LightViewMatrix );
glViewport( 0, 0, g_ScreenWidth, g_ScreenHeight );
// enable the shadowmapping GLSL program
glUseProgramObjectARB( g_prgShadowMap );
// enable and bind the shadow map we rendered above
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, g_ShadmapID );
GLuint uniform = glGetUniformLocationARB( g_prgShadowMap, "shadtex");
glUniform1iARB( uniform, 0 );
// actually render the scene as normal
RenderWorld();
glUseProgramObjectARB( NULL );
// return GL to normal state
glDisable( GL_TEXTURE_2D );
glDisable( GL_TEXTURE_GEN_S );
glDisable( GL_TEXTURE_GEN_T );
glDisable( GL_TEXTURE_GEN_R );
glDisable( GL_TEXTURE_GEN_Q );
Here’s my shaders:
// vertex
varying vec4 projcoord;
void main()
{
gl_Position = ftransform();
vec4 worldpos = gl_ModelViewMatrix * gl_Vertex;
projcoord = gl_TextureMatrix[0] * gl_Vertex;
vec4 lightdir = gl_LightSource[0].position - worldpos;
vec3 normal = normalize( gl_NormalMatrix * gl_Normal );
float NdotL = dot( normal, normalize(lightdir.xyz) );
gl_FrontColor = gl_Color * NdotL;
}
// fragment
uniform sampler2DShadow shadtex;
varying vec4 projcoord;
void main()
{
vec3 pos = projcoord.xyz/projcoord.q;
float shadval = shadow2DProj(shadtex,projcoord).r;
// only potentially in shadow if within the light's view frustum
if ( projcoord.w > 0.0 && pos.x >= 0.0 && pos.x <= 1.0 && pos.y >= 0.0 && pos.y <= 1.0 )
gl_FragColor = gl_Color * shadval;
else
"
gl_FragColor = gl_Color;
}
Any help at all would be appreciated, while I still have some hair left.