Jump to content
  • Advertisement
Sign in to follow this  
fcoelho

Shadow mapping difficulties

This topic is 2830 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to implement the simplest form of shadow mapping, and I can't get it to work. I must be doing something wrong with my matrix setup, so any thoughts are welcome. So far, my best result was a completely non-shadowed scene:

[attachment=1598:scene.png]

And this is the shadow map:

[attachment=1597:shadowmap.png]

My vertex shader:

[spoiler]
varying vec2 texCoord;
varying vec4 position;

uniform mat4 lightMatrix;

void main()
{
texCoord = gl_MultiTexCoord0.st;
position = lightMatrix * gl_Vertex;

gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
}
[/spoiler]

My fragment shader:

[spoiler]
uniform sampler2D shadowMap;
uniform sampler2D texture;

varying vec2 texCoord;
varying vec4 position;

void main()
{
vec4 shadowCoord = position / position.w;

float depthFromLight = texture2D(shadowMap, shadowCoord.st).r;
float depthFromCamera = shadowCoord.z;

float shadow = 1.0;
if (depthFromLight < depthFromCamera)
shadow = 0.5;

gl_FragColor = texture2D(texture, texCoord) * shadow;
}
[/spoiler]

The relevant code before rendering the scene for the second time:

[spoiler]
glUseProgram(shadow_map_program);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, fbo.zId);
glActiveTexture(GL_TEXTURE0);
glUniform1i(glGetUniformLocation(shadow_map_program, "texture"), 0);
glUniform1i(glGetUniformLocation(shadow_map_program, "shadowMap"), 1);
cml::matrix44f_c bias(
0.5, 0.0, 0.0, 0.5,
0.0, 0.5, 0.0, 0.5,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
);
cml::matrix44f_c lightMatrix = bias * matProjLight * matPosLight;
glUniformMatrix4fv(glGetUniformLocation(shadow_map_program, "lightMatrix"), 1, GL_FALSE, lightMatrix.data());
draw_scene(tex0, tex1);
[/spoiler]

[font="Courier New"]draw_scene [/font][font="Arial"]is a function that draws the two quads already in world space.[/font]

[font="Arial"]The vertex shader only converts those quads into clip space. I expected that if my fragment shader was only
gl_FragColor = texture2D(shadowMap, position.xy/position.w);
[/font][font="Arial"]then I'd see the shadow map perfectly rendered on top of the quads, but I actually see everything white, completely. What am I missing or where have I gone wrong?[/font]

Share this post


Link to post
Share on other sites
Advertisement
The bias matrix is responsible for converting clip coordinates to a "texture coordinate acceptable range", i.e., converting the range [-1,+1] to [0,1].

I solved the problem a few hours ago, it was actually a bug with my math library + compiler version, which caused the bias matrix to be built incorrectly, instead of the expected

[.5 0 0 .5]
[ 0 .5 0 .5]
[ 0 0 .5 .5]
[ 0 0 0 1]

it compiled into

[ 1 0 0 .5]
[ 0 0 0 0]
[ 0 0 0 0]
[ 0 0 0 0]


It's mostly working now, except for some shadows outside the light frustum which I haven't been able to remove. I'm going to post it back here when I get home.

Share this post


Link to post
Share on other sites
In the fragment shader, something is considered shadowed when

if (depthFromLight < depthFromCamera)
shadow = 0.5;



But this creates the following artifact:

[attachment=1626:samplingbehindfrustum.jpg]

I've tried to use what's on this site:

if (position.w > 0.0)

but it doesn't fix it, it stays the same. I tried to use a "inFrustum" variable to check whether I should check the shadow map for texturing:

bool inFrustum = shadowCoord.x > 0.0 && shadowCoord.x < 1.0 && shadowCoord.y > 0.0 && shadowCoord.y < 1.0;

But it creates another problem:

[attachment=1625:infrustum.jpg]

So, how do I fix this?

    Share this post


    Link to post
    Share on other sites
    I've tried to change my create_fbo function, especially the texture clamping modes to see if there was a change, but the "replica" of the shadow right above the correct one still appears. Any ideas on how do I fix it?

    FBO create_fbo(unsigned width, unsigned height)
    {
    FBO fbo;

    glGenFramebuffers(1, &fbo.id);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo.id);

    glGenTextures(1, &fbo.zId);
    glGenTextures(1, &fbo.cId);

    glBindTexture(GL_TEXTURE_2D, fbo.cId);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);

    glBindTexture(GL_TEXTURE_2D, fbo.zId);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    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, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo.cId, 0);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fbo.zId, 0);

    GLenum fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (fboStatus != GL_FRAMEBUFFER_COMPLETE)
    std::cerr << "Framebuffer incomplete\n";

    return fbo;
    }

    Share this post


    Link to post
    Share on other sites
    Sign in to follow this  

    • Advertisement
    ×

    Important Information

    By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

    GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

    Sign me up!