Error with shadow maps

Hey guys,
so im looking to implement cascading shadow maps, thought I am currently doing a very basic single map method (my first time doing shadows ) and have come across a error I cant fix.

here are the shaders (just drawing the shadows now, pow’d to be more visible


VERT

varying vec4 vPos;
varying vec2 texCoord;

void main(){
        vPos = gl_ModelViewMatrix * gl_Vertex;
        gl_Position = gl_ProjectionMatrix * vPos;

        texCoord = gl_MultiTexCoord0.st;
}


FRAG

uniform sampler2DShadow shadowmap;

varying vec4 vPos;
varying vec2 texCoord;

void main(){
        vec4 sc = gl_TextureMatrix[0] * vPos;

        float shadow = shadow2DProj( shadowmap, sc ).x;
        vec4 c = vec4( 1.0, 1.0, 1.0, 1.0 );

        vec4 color = mix( vec4( 0.8, 0.8, 0.8, 1.0 ),
                ( 0.9 * shadow  * c + 0.1 * c ),
                0.6 );

        shadow = pow(shadow, 32.0);

        gl_FragData[0] = vec4(shadow, shadow, shadow, 1.0 );
}

shadow creation


        glDisable( GL_TEXTURE_2D );

        glMatrixMode( GL_PROJECTION );
        glPushMatrix();

                glMatrixMode( GL_MODELVIEW );
                glPushMatrix();
                glLoadIdentity();

                        //camera.setView();
                        glRotatef( -90.0, 0.0, 1.0, 0.0 );
                        glTranslatef( 0.0, -10.0, -20.0 );

                        glGetFloatv( GL_MODELVIEW_MATRIX, shadow_mv );

                        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo );

                        glPushAttrib( GL_VIEWPORT_BIT );
                        glViewport( 0, 0, DEPTHSIZEW, DEPTHSIZEH );

                        glPolygonOffset( 1.0, 4096.0 );
                        glEnable( GL_POLYGON_OFFSET_FILL );

                        glDisable( GL_CULL_FACE );

                        glFramebufferTextureEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depth_tex, 0 );
                        glClear( GL_DEPTH_BUFFER_BIT );

                        glmDraw( building, GLM_SMOOTH | GLM_MATERIAL);

                        glMatrixMode( GL_PROJECTION );
                                glMultMatrixf( shadow_mv );
                                glGetFloatv( GL_PROJECTION_MATRIX, shadow_cpm );

                        //glEnable( GL_CULL_FACE );
                        glDisable(GL_POLYGON_OFFSET_FILL);
                        glPopAttrib();
                        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

                glMatrixMode(GL_MODELVIEW);
                glPopMatrix();

        glMatrixMode(GL_PROJECTION);
        glPopMatrix();

        glEnable(GL_TEXTURE_2D);

and the render code


        const float bias[16] = { 0.5, 0.0, 0.0, 0.0,
                                0.0, 0.5, 0.0, 0.0,
                                0.0, 0.0, 0.5, 0.0,
                                0.5, 0.5, 0.5, 1.0 };


        float cam_proj[16];
        float cam_mv[16];
        float cam_inv[16];

        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

        renderShadows();

        glslLoadProgram( shadowShader );

        glMatrixMode( GL_MODELVIEW );
        glLoadIdentity();

        camera.setView();

        //???
        glGetFloatv( GL_MODELVIEW_MATRIX, cam_mv );
        Inverse( cam_inv, cam_mv );


        glActiveTexture( GL_TEXTURE0 );
        glBindTexture( GL_TEXTURE_2D, depth_tex );
        //glTexParameteri( GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_COMPARE_MODE, GL_NONE );
        //glTexParameteri( GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);   

        ///???
        glMatrixMode(GL_TEXTURE);
                glLoadMatrixf( bias );
                glMultMatrixf( shadow_cpm );
                glMultMatrixf( cam_inv );

        glmDraw( building, GLM_SMOOTH | GLM_MATERIAL);

        glslUnloadProgram();

        if( showShadows )
                displayShadows();

        SDL_GL_SwapBuffers();

dont get what’s wrong with this, any help would be great

It helps to visualize the frustum regions. Try alpha blending the slabs in different colors.

Probably easier to start with a working demo if you can then peel it down to a version of your liking.

Sorry I dont get what you mean.

I think he’s saying, once you get to the CSM stage, show which fragments are in which slab using some colors you blend in (e.g. red for closest frustum, green for next closests, etc.).

However I think you said you’re just doing single map right now. It’s hard to see what you have really. I’d try rotating the eye toward the light so the frustums aligned more closely to see if what you have makes any sense at all.

I’d also try coloring every other shadow texel with a different color in the final rendering (e.g. red-and-green checkerboard). That way you can easily see the perspective and projection aliasing of the shadow map pixels on your objects. Since there’s no “depth compare”, this will also get rid of the Z inaccuracy problems, which will help you establish whether that’s a problem. Also, this’ll help you verify your eye to light space transform is correct.

Yep, and also helpful I think to unproject the unit cube into world space, to visualize the frustum you’re creating and debug your transformations (xform ass-hattery is the bane of any shadow mapper).

I am sorry, and probably seem dumb, but I really dont understand much of what you guys are saying lol.
I have viewed the shadow map and it is coming out right, also moveing the camera near the light come out ok. There are a few spots that are not shaded ( come out white ) which worry me but I believe those will clear up when I slove the bigger issue.
As for unprojecting the unit cube, how would I go about doing this??

Thanks for your help guys.

glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glMultMatrixf(viewProjInverse);
DrawMesh(unitCube);
glPopMatrix();

not sure if I got the projection inverse right, I took the projection matrix muled it by the modelview, grab that matrix and inversed it.
if this is right then the unit cube is off

changed from GL_CLAMP to GL_CLAMP_TO_BORDER and now I have this.

looks pretty good, I believe the multiple levels of hardness on the end are because there are several towers on the abby. However it seems to be mirroring the shadow area… Any ideas why or how to fix this?

edit: been reading about this, dont belive that this will do what I need, everyone says to use *TO_EDGE but that produces the same as the first picture… -_-

Gah still stuck with this error… -___- any other ideas?

>> However it seems to be mirroring the shadow area… Any ideas why or how to fix this?

this is the standard backprojection problem, theres a few solutions have a look at old pdf papers

one method is call fragment discard for any fragments behind the lights forward direction plane

When you are in such situation, I recommend to simplify as much as possible your code to isolate the problem.
Choose camera and light particular positions so that you can easily debug transformations by all set matrices. Get all used matrix (glGetFloatfv) perform all transformations and see if the result is correct. Vizualize the content of the depth buffer.

Do all this step by step: For example:

  1. do light setup -> if if matrices are correct (move for example camera at the light position)
  2. draw shadow map -> see if it is correct (render on a screen aligned quad with a shader, write it in a file).
  3. Render from light : check matrices states. Do not forget to biais fragment position after transforming it in light clip space.

Worked great. Got that error fixed. Its producint REALLY hard shadows right now, that are aliased even at higher resoultions (1024x1024 when the normal screen is 640x480 ) but I’ll fix / work on this some more. Also I dont get why the shadow map is showing it going straight across rather then looking like a fulcrum, if anyone knows that would be great, but not really a big issue.

heres the code…


VERT
varying vec4 vPos;
varying vec2 texCoord;
void main(){
        vPos = gl_TextureMatrix[0] * gl_Vertex; //using this, no need to mul the matrix by the camera's inverse
        gl_Position = ftransform();

        texCoord = gl_MultiTexCoord0.st;
}

FRAG
uniform sampler2DShadow shadowmap;

varying vec4 vPos;
varying vec2 texCoord;

void main(){
        float shadow = shadow2DProj( shadowmap, vPos ).r;
        vec4 c = vec4( 1.0, 1.0, 1.0, 1.0 ); //temp color

        //check to make sure the shadow is in bounds,
        //if not discard it (this should allow us to render with textures and colors in the same path
        if( vPos.w < 1.0 )
                shadow = 0.0;

        vec4 color = mix( vec4( 0.8, 0.8, 0.8, 1.0 ),
                ( 0.9 * shadow  * c + 0.1 * c ),
                0.6 );

        gl_FragData[0] = color;
}

getting the shadow maps


void renderShadows(){
        glLoadIdentity();

        //set and push the matrix stacks so nothing is saved
        glMatrixMode( GL_PROJECTION );
        glPushMatrix();

                glMatrixMode( GL_MODELVIEW );
                glPushMatrix();

                        glPushAttrib( GL_VIEWPORT_BIT );
                        glViewport(0, 0, DEPTHSIZEW, DEPTHSIZEH );

                        //prevent z-fighting
                        glPolygonOffset( 1.0, 4096.0 );
                        glEnable( GL_POLYGON_OFFSET_FILL );

                        //bind the fbo and depth map so we can render to them
                        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
                        glClear( GL_DEPTH_BUFFER_BIT );

                        glRotatef( -90.0, 0.0, 1.0, 0.0 );
                        glTranslatef( 0.0, -10.0, -20.0 );

                        glGetFloatv( GL_MODELVIEW_MATRIX, shadow_mv );

                        glmDraw( building, GLM_SMOOTH );

                        glDisable( GL_POLYGON_OFFSET_FILL );
                        glPopAttrib();

                        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

                glPopMatrix();

        glMatrixMode( GL_PROJECTION );
                glMultMatrixf( shadow_mv );
                glGetFloatv( GL_PROJECTION_MATRIX, shadow_cpm );

        glPopMatrix();

        glMatrixMode( GL_MODELVIEW );
}

drawing the scene


void render(){
        const float bias[16] = { 0.5, 0.0, 0.0, 0.0,
                                0.0, 0.5, 0.0, 0.0,
                                0.0, 0.0, 0.5, 0.0,
                                0.5, 0.5, 0.5, 1.0 };

        renderShadows();

        glslLoadProgram( shadowShader );

        glLoadIdentity();
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

        camera.setView();

        glActiveTexture( GL_TEXTURE0 );
        glBindTexture( GL_TEXTURE_2D, depth_tex );
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);

        //set up the texture matrix so the shadows are calculated correctly
        glMatrixMode(GL_TEXTURE);
                glLoadMatrixf( bias );
                glMultMatrixf( shadow_cpm );

        glMatrixMode(GL_MODELVIEW);

        glmDraw( building, GLM_SMOOTH );

        glslUnloadProgram();

        if( showShadows )
                displayShadows();

        SDL_GL_SwapBuffers();
}

and creating the shadow maps / fbo


bool InitFBO(){
        //set up the depth texture
        glGenTextures(1, &depth_tex);
        glBindTexture(GL_TEXTURE_2D, depth_tex);
        //NOTE: linear causes better shadows, possible to mipmap the shadows??
        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);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, DEPTHSIZEW, DEPTHSIZEH, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);

        //into the void you go
        glBindTexture( GL_TEXTURE_2D, 0 );

        glGenFramebuffersEXT( 1, &fbo );
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
        glDrawBuffer(GL_NONE); //tell the fbo to draw nothing (depth only)

        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT ,GL_TEXTURE_2D, depth_tex, 0);

        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );


        return true;
}