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.
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