2

In my shadow map implementation for directional lights I have a collection of items which I iterate them to render their depth to a depth buffer then iterate them again to render them normally with the generated shadow map, each item has a bool property called castShadow which I test if true add it to the depth buffer, the problem is if the item cast shadow and rendered to the depth buffer it can't receive shadows at all, once I set the to false then it is not rendered as depth it start to receive shadows without problem. so in render function first I render the depth buffer as following:

When the object cast shadow it doesn't receive shadows When the object cast shadow it doesn't receive shadows

When the object isn't cast shadow it receives shadows When the object isn't cast shadow it receives shadows

void Engine::renderDepthMaps() {
    if (sun != nullptr) {
        if (sun->castShadow) {
            glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
            glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
            glClear(GL_DEPTH_BUFFER_BIT);
            glm::vec3 pos = -500.0f * sun->direction;
            glm::mat4 lightSpaceProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, -10.0f, 1000.0f);
            glm::mat4 lightSpaceView = glm::lookAt(pos, player->getPosition(), glm::vec3(0, 1, 0));
            lightSpaceMatrix = lightSpaceProjection * lightSpaceView;
            Shader& shader = shaders.getShader(DEPTH);
            shader.use();
            shaders.setDepthLightSpaceUniform(shader, lightSpaceMatrix);
            for (item_it it = engineItems.begin(); it != engineItems.end(); ++it) {
                if (it->get()->castShadow)
                    it->get()->renderDepth(deltaFirst);
            }
            glBindFramebuffer(GL_FRAMEBUFFER, 0);
        }
    }
}

and the render function is:

void Engine::renderMeshes() {
    glViewport(0, 0, width, height);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    Shader& basicShader = shaders.getShader(BASIC);
    basicShader.use();
    sun->setUniforms(basicShader.getProgramID(), "directLights");
    shaders.setLightSpaceUniform(basicShader, sun, lightSpaceMatrix, depthMap);
    shaders.setShaderViewUniforms(basicShader, camera);
    terrain->render(basicShader, deltaFirst);
    for (item_it it = basicItems.begin(); it != basicItems.end(); ++it) {
        if (it->get()->type != "terrain")
            it->get()->render(basicShader, deltaFirst);
    }
}

and the shaders are: vertex:

    #version 300 es
precision highp float;

layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 lightSpaceMatrix;  
uniform mat3 normalMatrix;

out vec4 FragPosLightSpace;
out vec2 TexCoords;
out vec3 Normal;
out vec3 viewPos;
out vec3 fragPos;

void main(){    
    TexCoords = texCoord;   
    Normal=normalMatrix*normal; 
    fragPos = vec3(model * vec4(position,1.0f));
    FragPosLightSpace =lightSpaceMatrix * model * vec4(position,1.0f);
    gl_Position = projection * view * model * vec4(position,1.0f);          
}

fragment:

    #version 300 es
precision highp float;

out vec4 glFragColor;

vec2 poissonDisk[4] = vec2[](
  vec2( -0.94201624, -0.39906216 ),
  vec2( 0.94558609, -0.76890725 ),
  vec2( -0.094184101, -0.92938870 ),
  vec2( 0.34495938, 0.29387760 )
);

struct DirectLight {
    vec3 direction;
    vec3 color;
    float intensity;        
};

in vec3 Normal;
in vec2 TexCoords;
in vec3 fragPos;
in vec4 FragPosLightSpace;

uniform int has_texture;
uniform vec3 matDiffuse;
uniform sampler2D  shadowMap;
uniform sampler2D  mat_diffuse;
uniform sampler2D mat_specular;
uniform vec3 matSpecular;
uniform float shininess;
uniform DirectLight sun;
uniform int castShadow;
uniform vec3 viewPos;

void main(){   
    vec3 tex=vec3(1),spe=vec3(1);
    if(has_texture==1){
        tex=vec3(texture(mat_diffuse, TexCoords));
        spe=vec3(texture(mat_specular,TexCoords));
    }
    vec3 diffColor   = matDiffuse  * tex;   
    vec3 specColor   = matSpecular * spe;
    vec3 ambient     = vec3(0.4,0.4,0.4)*diffColor;
    vec3 lightDir    = normalize(-sun.direction);

    float diff       = max(dot(Normal,lightDir), 0.0);
    vec3  diffuse    = sun.color * diff * diffColor;

    vec3  viewDir    = normalize(viewPos - fragPos);        
    vec3  reflectDir = reflect(-lightDir, Normal);  
    float spec       = pow(max(dot(viewDir, reflectDir), 0.0), shininess);
    vec3  specular   = spec * specColor * sun.color;

    vec3  color      = ambient + diffuse + specular;
    float gamma = 2.2;
    color.rgb = pow(color.rgb, vec3(1.0/gamma));
    if(castShadow==1){          
        vec3 projCoords = FragPosLightSpace.xyz / FragPosLightSpace.w;
        projCoords = projCoords * 0.5 + 0.5;
        float shadow = 1.0; 
        for (int i=0;i<4;i++){
            shadow -= 0.2*(1.0-texture( shadowMap, projCoords.xy + poissonDisk[i]/700.0).r);
        } 
        if(projCoords.z > 1.0)
            shadow = 0.0; 
        color *=shadow;
    }           
    glFragColor=vec4(color,1.0f);
}

Another problem: the light space perspective matrix is glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, -10.0f, 1000.0f) and the shadow map size is 1024, when an object is outside that matrix it create very long shadow and is not in the correct direction as shown in the following image: enter image description here

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982

0 Answers0