0
\$\begingroup\$

I am encountering some weird artefacts when rendering shadows using a shadow map.

I am using C++ with Vulkan and GLSL shaders.

enter image description here

This is the vertex shader that calculates the light_space_position:

#version 450

layout(location = 0) in vec3 in_position;
layout(location = 1) in vec3 in_normal;
layout(location = 2) in vec2 in_uv;

layout(location = 0) out vec3 out_position;
layout(location = 1) out vec3 out_normal;
layout(location = 2) out vec2 out_uv;
layout(location = 3) out vec4 out_light_space_position;

layout(binding = 0) uniform uniform_scene {
  mat4 view;
  mat4 projection;
  vec3 camera_position;
  mat4 light_space;
} scene;

void main() {
  out_position = vec3(object.model * vec4(in_position, 1.0));
  out_normal = normalize(mat3(object.normal) * in_normal);
  out_uv = in_uv;
  out_light_space_position = scene.light_space * vec4(out_position, 1.0);

  gl_Position = scene.projection * scene.view * vec4(out_position, 1.0);
}

This is the fragment shader code:

layout(location = 0) in vec3 in_position;
layout(location = 1) in vec3 in_normal;
layout(location = 2) in vec2 in_uv;
layout(location = 3) in vec4 in_light_space_position;

layout(location = 0) out vec4 out_color;

layout(binding = 0) uniform uniform_scene {
  mat4 view;
  mat4 projection;
  vec3 camera_position;
  mat4 light_space;
} scene;

layout(binding = 2) uniform sampler2D image;
layout(binding = 3) uniform sampler2D shadow_map;

const vec3 light_position = vec3(2.0, 5.0, 2.0);

float calculate_shadow(vec4 light_space_position, vec3 light_dir) {
  vec3 projection_coords = light_space_position.xyz / light_space_position.w;

  projection_coords = projection_coords * 0.5 + 0.5;

  float current_depth = projection_coords.z;

  float closest_depth = texture(shadow_map, projection_coords.xy).r;

  float bias = max(0.05 * (1.0 - dot(in_normal, light_dir)), 0.005);

  return (current_depth - bias) > closest_depth ? 1.0 : 0.0;
}

void main() {
  vec4 color = texture(image, in_uv);

  vec4 light_color = vec4(1.0, 1.0, 1.0, 1.0);
  // ambient
  vec4 ambient = 0.15 * light_color;
  // diffuse
  vec3 light_dir = normalize(light_position - in_position);
  float diff = max(dot(light_dir, in_normal), 0.0);
  vec4 diffuse = diff * light_color;
  // specular
  vec3 view_dir = normalize(scene.camera_position - in_position);
  float spec = 0.0;
  vec3 halfway_dir = normalize(light_dir + view_dir);  
  spec = pow(max(dot(in_normal, halfway_dir), 0.0), 64.0);
  vec4 specular = spec * light_color;    
  // calculate shadow
  float shadow = calculate_shadow(in_light_space_position, light_dir);  

  out_color = (ambient + (1.0 - shadow) * (diffuse + specular)) * color;
}

\$\endgroup\$

0

You must log in to answer this question.

Browse other questions tagged .