Search code examples
c++openglglfwglm-mathshadow-mapping

openGL shadow mapping but everything is black


I first made a scene with no shadowing and tested it with good results, then I was trying to make shadows for my scene, which resulted in every object being black. However, my remaining features function normally.

I think there might be some uniform values that are not correctly assigned, but I can't identify them.

here are my code fragments:

getSceneVertShader()

return  "#version 330 core\n"
        "uniform vec3 view_position;"
        ""
        "layout(location = 0) in vec3 position;"
        "layout(location = 1) in vec3 normals;"
        ""
        "uniform mat4 worldMatrix;"
        "uniform mat4 viewMatrix;"
        "uniform mat4 projectionMatrix;"
        "uniform mat4 lightSpaceMatrix;"
        ""
        "out vec3 fragment_normal;"
        "out vec3 fragment_position;"
        "out vec4 fragment_position_light_space;"
        ""
        "void main()"
        "{"
        "   fragment_normal = mat3(worldMatrix) * normals;"
        "   fragment_position = vec3(worldMatrix * vec4(position, 1.0));"
        "   fragment_position_light_space = lightSpaceMatrix * vec4(fragment_position, 1.0);"
        "   gl_Position = projectionMatrix * viewMatrix * worldMatrix * vec4(position, 1.0);"
        "}";

getSceneFragShader()

return      "#version 330 core\n"
            "const float PI = 3.1415926535897932384626433832795;"
            ""
            "uniform vec3 light_color;"
            "uniform vec3 light_position; "
            "uniform vec3 light_direction; "
            ""
            "uniform vec3 overrideColor; "
            ""
            "const float shading_ambient_strength    = 0.1;"
            "const float shading_diffuse_strength    = 0.6;"
            "const float shading_specular_strength   = 0.3;"
            ""
            "uniform float light_cutoff_outer; "
            "uniform float light_cutoff_inner; "
            "uniform float light_near_plane; "
            "uniform float light_far_plane; "
            ""
            "uniform vec3 view_position; "
            ""
            "uniform sampler2D shadow_map; "
            ""
            "in vec3 fragment_position; "
            "in vec4 fragment_position_light_space; "
            "in vec3 fragment_normal; "
            ""
            "in vec4 gl_FragCoord; "
            ""
            "out vec4 result; "
            ""
            "vec3 ambient_color(vec3 light_color_arg) {"
            "    return shading_ambient_strength * light_color_arg; "
            "}"
            ""
            "vec3 diffuse_color(vec3 light_color_arg, vec3 light_position_arg) {"
            "    vec3 light_direction = normalize(light_position_arg - fragment_position); "
            "    return shading_diffuse_strength * light_color_arg *" "max(dot(normalize(fragment_normal), light_direction), 0.0f); "
            "}"
            ""
            "vec3 specular_color(vec3 light_color_arg, vec3 light_position_arg) {"
            "    vec3 light_direction = normalize(light_position_arg - fragment_position); "
            "    vec3 view_direction = normalize(view_position - fragment_position); "
            "    vec3 reflect_light_direction = reflect(-light_direction, normalize(fragment_normal));"
            ""
            "    return shading_specular_strength * light_color_arg *" "pow(max(dot(reflect_light_direction, view_direction), 0.0f),32); "
            "}"
            ""
            "float shadow_scalar() {"
        // this function returns 1.0 when the surface receives light, and 0.0 when it is in a shadow
        // perform perspective divide
            "    vec3 normalized_device_coordinates = fragment_position_light_space.xyz / fragment_position_light_space.w; "
        // transform to [0,1] range
            "    normalized_device_coordinates = normalized_device_coordinates * 0.5 + 0.5; "
        // get closest depth value from light's perspective (using [0,1] range fragment_position_light_space as coords) 
            "    float closest_depth = texture(shadow_map, normalized_device_coordinates.xy).r; "
        // get depth of current fragment from light's perspective
            "    float current_depth = normalized_device_coordinates.z; "
        // check whether current frag pos is in shadow
        // bias applied in depth map: see shadow_vertex.glsl
            "    float bias = 0.006;  "
            "    return ((current_depth - bias) < closest_depth) ? 1.0 : 0.0; "
            "}"
            ""
            "float spotlight_scalar() {"
            "    float theta = dot(normalize(fragment_position - light_position), light_direction); "
            ""    
            "    if(theta > light_cutoff_inner) {"
            "        return 1.0; "
            "    } else if(theta > light_cutoff_outer) {"
            "        return (1.0 - cos(PI * (theta - light_cutoff_outer) / (light_cutoff_inner - light_cutoff_outer))) / 2.0; "
            "    } else {"
            "        return 0.0; "
            "    }"
            "}"
            ""
            "void main()"
            "{"
            "    vec3 ambient = vec3(0.0f); "
            "    vec3 diffuse = vec3(0.0f); "
            "    vec3 specular = vec3(0.0f); "
            ""
            "    float scalar = shadow_scalar() * spotlight_scalar();"
            "    ambient = ambient_color(light_color); "
            "    diffuse = scalar * diffuse_color(light_color, light_position); "
            "    specular = scalar * specular_color(light_color, light_position); "
            ""    
            "    vec3 color = (specular + diffuse + ambient) * overrideColor;"
            ""   
            "    result = vec4(color, 1.0f); "
            "}";

getShadowVertShader()

return
        "#version 330 core\n"
        "layout(location = 0) in vec3 position;"
        ""
        "uniform mat4 lightSpaceMatrix;"
        "uniform mat4 worldMatrix;"
        ""
        "void main()"
        "{"
        "   gl_Position ="
        ""
        "   lightSpaceMatrix * worldMatrix * vec4(position, 1.0);"
        "}";

getShadowFragShader()

 return
        "#version 330 core\n"
        ""
        "out vec4 FragColor;"
        "in vec4 gl_FragCoord;"
        "void main()"
        "{"
        "   gl_FragDepth = gl_FragCoord.z;"
        "   FragColor = vec4(vec3(gl_FragCoord.z), 1.0f);"
        "}";

createVertexArrayObject(const glm::vec3* vertexArray, int arraySize)

    glGenVertexArrays(1, &vertexArrayObject);
    glBindVertexArray(vertexArrayObject);

    GLuint vertexBufferObject;
    glGenBuffers(1, &vertexBufferObject);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER, arraySize, vertexArray, GL_STATIC_DRAW);

    glVertexAttribPointer(0,                   // attribute 0 matches aPos in Vertex Shader
        3,                   // size
        GL_FLOAT,            // type
        GL_FALSE,            // normalized?
        2*sizeof(glm::vec3), // stride - each vertex contain 2 vec3 (position, color)
        (void*)0             // array buffer offset
    );
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1,                    // attribute 1 matches aNormal in Vertex Shader
        3,                    // size
        GL_FLOAT,             // type
        GL_FALSE,             // normalized?
        2 * sizeof(glm::vec3),     // stride - each vertex contain 1 vec3 (position)
        (void*)(sizeof(glm::vec3)) // array buffer offset
    );
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    return vertexArrayObject;

main()

glfwInit();
    GLFWwindow* window = glfwCreateWindow(1024, 768, "some programs", NULL, NULL);

    glfwMakeContextCurrent(window);

    glewExperimental = true; // Needed for core profile
    if (glewInit() != GLEW_OK) {
        std::cerr << "Failed to create GLEW" << std::endl;
        glfwTerminate();
        return -1;
    }
  
    glClearColor(0.2f, 0.298f, 0.298f, 1.0f);

    float lastFrameTime = glfwGetTime();

    // Compile and link shaders here ...
    int shaderProgram = compileAndLinkSceneShaders();
    int shadowShaderProgram = compileAndLinkShadowShaders();

    /*bind vao */

    const unsigned int DEPTH_MAP_TEXTURE_SIZE = 1024;
    /*other variables initionalizations*/
    glm::vec3 lightInvDir = glm::vec3(0.5f, 2, 2);


    GLuint depth_map_texture;
    glGenTextures(1, &depth_map_texture);
    glBindTexture(GL_TEXTURE_2D, depth_map_texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, DEPTH_MAP_TEXTURE_SIZE, DEPTH_MAP_TEXTURE_SIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
        NULL);
    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_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);


    GLuint depth_map_fbo;
    glGenFramebuffers(1, &depth_map_fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, depth_map_fbo);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_map_texture, 0);
    glDrawBuffer(GL_NONE);

    GLuint shadowMatrixLocation = glGetUniformLocation(shaderProgram, "lightSpaceMatrix");
    GLuint projectionMatrixLocation = glGetUniformLocation(shaderProgram, "projectionMatrix");
    GLuint viewMatrixLocation = glGetUniformLocation(shaderProgram, "viewMatrix");
    GLuint colorLocation = glGetUniformLocation(shaderProgram, "overrideColor");
    GLuint worldMatrixLocation = glGetUniformLocation(shaderProgram, "worldMatrix");
    GLuint lightInnerLocation = glGetUniformLocation(shaderProgram, "light_cutoff_inner");
    GLuint lightOuterLocation = glGetUniformLocation(shaderProgram, "light_cutoff_outer");
    GLuint lightColorLocation = glGetUniformLocation(shaderProgram, "light_color");
    GLuint lightPositionLocation = glGetUniformLocation(shaderProgram, "light_position");
    GLuint lightDirectionLocation = glGetUniformLocation(shaderProgram, "light_direction");
    GLuint viewPositionLocation = glGetUniformLocation(shaderProgram, "view_position");
    GLuint lightNearLocation = glGetUniformLocation(shaderProgram, "light_near_plane");
    GLuint lightFarLocation = glGetUniformLocation(shaderProgram, "light_far_plane");

    GLuint shadowWorldMatrixLocation = glGetUniformLocation(shadowShaderProgram, "worldMatrix");
    GLuint shadowShadowMatrixLocation = glGetUniformLocation(shadowShaderProgram, "lightSpaceMatrix");

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    
    float lightAngleOuter = 30.0;
    float lightAngleInner = 20.0;
    // Set light cutoff angles on scene shader
    glUniform1f(lightInnerLocation, cos(glm::radians(lightAngleInner)));
    glUniform1f(lightOuterLocation, cos(glm::radians(lightAngleOuter)));

    // Set light color on scene shader
    
    GLfloat lightColor[3] = { 1.0f, 1.0f, 1.0f };
    glUniform3fv(lightColorLocation,1, &lightColor[0]);

    while (!glfwWindowShouldClose(window))
    {
        float dt = glfwGetTime() - lastFrameTime;
        lastFrameTime += dt;
        
        //set the camera
        glm::vec3 cameraPos = glm::vec3(cameraPan, 2.0f, cameraZoom + 6.0f);
        glm::mat4 viewMatrix = glm::lookAt(cameraPos,
            glm::vec3(cameraPan, cameraTilt + 2.0f, cameraZoom),
            glm::vec3(0.0f, 1.0f, 0.0f));
        glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, &viewMatrix[0][0]);

        glUniform3fv(viewPositionLocation, 1, &cameraPos[0]);

        glm::mat4 projectionMatrix = glm::perspective(glm::radians(45.0f),  // field of view in degrees
            1024.0f / 768.0f,      // aspect ratio
            0.01f, 100.0f);       // near and far (near > 0)
        glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, &projectionMatrix[0][0]);

        glm::vec3 lightPosition = glm::vec3(1.0f, 2.0f, 5.0f); // the location of the light in 3D space
        glm::vec3 lightFocus(0.0, 0.0, -1.0);      // the point in 3D space the light "looks" at
        glm::vec3 lightDirection = normalize(lightFocus - lightPosition);

        float lightNearPlane = 1.0f;
        float lightFarPlane = 180.0f;

        glm::mat4 lightProjectionMatrix = glm::frustum(-1.0f, 1.0f, -1.0f, 1.0f, lightNearPlane, lightFarPlane);
        //perspective(20.0f, (float)DEPTH_MAP_TEXTURE_SIZE / (float)DEPTH_MAP_TEXTURE_SIZE, lightNearPlane, lightFarPlane);
        glm::mat4 lightViewMatrix = glm::lookAt(lightPosition, lightFocus, glm::vec3(0.0f, 1.0f, 0.0f));
        glm::mat4 lightSpaceMatrix = lightProjectionMatrix * lightViewMatrix;
        glUniformMatrix4fv(shadowMatrixLocation, 1, GL_FALSE, &lightSpaceMatrix[0][0]);
        glUniformMatrix4fv(shadowShadowMatrixLocation, 1, GL_FALSE, &lightSpaceMatrix[0][0]);
        glUniform1f(lightNearLocation, lightNearPlane);
        glUniform1f(lightFarLocation, lightFarPlane);
        glUniform3fv(lightPositionLocation, 1, &lightPosition[0]);
        glUniform3fv(lightDirectionLocation, 1, &lightDirection[0]);

        glUseProgram(shadowShaderProgram);
        glViewport(0, 0, DEPTH_MAP_TEXTURE_SIZE, DEPTH_MAP_TEXTURE_SIZE);
        // Bind depth map texture as output framebuffer
        glBindFramebuffer(GL_FRAMEBUFFER, depth_map_fbo);
        // Clear depth data on the framebuffer
        glClear(GL_DEPTH_BUFFER_BIT);

        /*draw items*/
        //assigned overrideColor and using shadowShaderProgram to draw

        glBindVertexArray(0);

        glUseProgram(shaderProgram);

        int width, height;
        glfwGetFramebufferSize(window, &width, &height);
        glViewport(0, 0, width, height);
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        // Each frame, reset color of each pixel to glClearColor
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        /*draw items*/
        //assigned overrideColor and using shaderProgram to draw

        glBindVertexArray(0);




        glfwSwapBuffers(window);
        glfwPollEvents();

Solution

  • Solved

    everything about my code seems right, except for this part in main():

        float lightAngleOuter = 30.0;
        float lightAngleInner = 20.0;
        // Set light cutoff angles on scene shader
        glUniform1f(lightInnerLocation, cos(glm::radians(lightAngleInner)));
        glUniform1f(lightOuterLocation, cos(glm::radians(lightAngleOuter)));
    
        // Set light color on scene shader
        
        GLfloat lightColor[3] = { 1.0f, 1.0f, 1.0f };
        glUniform3fv(lightColorLocation,1, &lightColor[0]);
    

    to fix this, just move this part into the while loop and all set.