Advertisement

Variance Shadow mapping with Deferred Rendering?? not working

Started by July 02, 2018 06:25 PM
0 comments, last by Charlie Wheate 6 years, 7 months ago

Hey :) for a while now we have been using classic shadow mapping with PCF and have decided to upgrade to a more faster and efficient method of shadow mapping, variance shadow mapping, but I am getting problems with trying to implement variance shadow mapping with a deferred renderer. Below is an image of the result I am getting.

4ns9p.png

as you can see the shadows are not casting correctly. The code below is all the code you need.

GBuffer vertex shader

#version 330 core

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 texcoord;
layout(location = 2) in vec3 normal;
layout(location = 3) in vec3 tangent;

out vec3 _texcoord;
out vec3 _normal;
out vec3 _tangent;
out vec3 _frag_pos;

uniform mat4 mod;
uniform mat4 view;
uniform mat4 proj;
uniform mat4 lightSpaceMatrix;

void main()
{
    vec4 world_space = mod * vec4(position, 1.0);

    _frag_pos = world_space.xyz;
    _texcoord = texcoord;

    _normal = (mod * vec4(normal, 0.0)).xyz;
    _tangent = (mod * vec4(tangent, 0.0)).xyz;

    gl_Position = proj * view * world_space;
}

Light fragment shader (directional light calculation)

vec3 calc_directional_light(vec3 Diffuse, vec3 Specular, vec3 Metalness, float ao)
{
    vec3 Ambient = vec3(0.3, 0.3, 0.3);

    vec3 light_colour = lightColour * lightIntensity;
    vec3 lighting = Ambient * Diffuse * ao;
    vec3 viewDir = normalize(camera_pos - FragPos);
    vec3 lightDir = normalize(lightPos - FragPos);
    vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Diffuse * light_colour;    

    vec4 vShadowCoords = lightSpaceMatrix * vec4(FragPos, 1.0);

    if(vShadowCoords.w > 1) 
    {

        //divide the shadow coordinate by homogeneous coordinate
        vec3 uv = vShadowCoords.xyz / vShadowCoords.w;

        //get the depth value
        float depth = uv.z;

        //read the moments from the shadow map texture
        vec4 moments = texture(gShadowmap, uv.xy); 

        //calculate variance from the moments
        float E_x2 = moments.y;
        float Ex_2 = moments.x*moments.x;
        float var = E_x2-Ex_2;

        //bias the variance
        var = max(var, 0.00002);

        //subtract the fragment depth from the  first moment
        //divide variance by the squared difference value
        //to get the maximum probability of fragment to be in shadow
        float mD = depth-moments.x;
        float mD_2 = mD*mD; 
        float p_max = var/(var+ mD_2); 

        //darken the diffuse component if the current depth is less than or equal
        //to the first moment and the retured value is less than the calculated
        //maximum probability
        diffuse *= max(p_max, (depth<=moments.x)?1.0:0.2); 
    }

    vec3 halfwayDir = normalize(lightDir + viewDir);
    float spec = pow(max(dot(Normal, halfwayDir), 0.0), 32.0);
    vec3 specular = (Specular * light_colour) * spec;

    vec3 metalness = Metalness * Diffuse * ao;

    lighting += (diffuse + specular + metalness);

    return lighting;
}

Rendering to shadowmap

inline virtual void Render()
{
    glDisable(GL_BLEND);        // Disable blending for opique materials
    glEnable(GL_DEPTH_TEST);    // Enable depth test to avoid quads rendering on top of each other that shouldnt
    glDisable(GL_CULL_FACE);    // Disable cull face so the shadowmap does not have the far plane bugs

    glm::mat4 model;  // model matrix for all the meshes in the shadowmap

    light_projection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, 1.0f, 25.0f); // project onto the scene from the position of the light (sun)
    light_view = glm::lookAt(glm::vec3(2.0f, 4.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f)); // position the camera at the lights position
    light_space_matrix = light_projection * light_view * glm::inverse(Content::_map->GetCamera()->GetViewMatrix()); // calculate the lightSpaceMatrix

    glUseProgram(_shader_programs[0]); // bind the first pass shader

    glUniformMatrix4fv(_u_lsm, 1, GL_FALSE, glm::value_ptr(light_space_matrix)); // set the lightSpaceMatrix uniform

    glViewport(0, 0, _shadowmap_resolution, _shadowmap_resolution); // set the viewport size to the resolution of the shadow map
    _fbos[0]->Bind();
    glClear(GL_DEPTH_BUFFER_BIT); // clear any depth info

    // loop through all the meshes within the scene
    for (unsigned int i = 0; i < Content::_map->GetActors().size(); i++)
    {
        model = Content::_map->GetActors()[i]->GetModelMatrix() * Content::_map->GetCamera()->GetViewMatrix(); // get the model matrix in viewspace for all the meshes

        glUniformMatrix4fv(_u_mod, 1, GL_FALSE, glm::value_ptr(model)); // set the viewspace model matrix uniform

        Content::_map->GetActors()[i]->Render(); // render all the meshes into the shadowmap
    }

    _fbos[0]->Unbind(); // unbind the shadowmap fbo

    glViewport(0, 0, 1920, 1080); // reset the viewport
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // glclear the gbuffer before rendering to it
    glEnable(GL_CULL_FACE); // enable cull face
}

For blurring the shadows I use a simple guassian blur shader.

 

Any ideas as to why this might be happening?

help is much appriecated

is it possible to do variance shadows and deferred rendering? if so a quick overview on how to do it would be great

This topic is closed to new replies.

Advertisement