#version 330 core in VS_OUT { vec4 frag_pos_light_space; vec3 frag_pos; vec3 normal; vec2 tex_coords; } fs_in; out vec4 frag_color; uniform vec3 light_pos; uniform vec3 view_pos; uniform sampler2D diffuse_texture; uniform sampler2D shadow_map; float calculate_shadow() { vec3 proj_coords = fs_in.frag_pos_light_space.xyz/fs_in.frag_pos_light_space.w; proj_coords = proj_coords*0.5+0.5; float closest_depth = texture(shadow_map, proj_coords.xy).r; float current_depth = proj_coords.z; vec3 normal = normalize(fs_in.normal); vec3 light_dir = normalize(light_pos-fs_in.frag_pos); float bias = max(0.04*(1.0-dot(normal, light_dir)), 0.004); float shadow = 0; vec2 texel_size = 1.0/textureSize(shadow_map, 0); for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { float pcf_depth = texture(shadow_map, proj_coords.xy+vec2(x, y)*texel_size).r; shadow += (current_depth-bias > pcf_depth) ? 1.0 : 0.0; } } shadow /= 9.0; if (proj_coords.z > 1.0) shadow = 0.0; return(shadow); } void main(void) { vec3 color = texture(diffuse_texture, fs_in.tex_coords).rgb; vec3 normal = normalize(fs_in.normal); vec3 light_color = vec3(0.3); float ambient_strength = 0.01; vec3 ambient = color*ambient_strength; vec3 light_dir = normalize(light_pos-fs_in.frag_pos); float diff = max(dot(light_dir, normal), 0.0); vec3 diffuse = diff*color; vec3 view_dir = normalize(view_pos-fs_in.frag_pos); vec3 halfway_dir = normalize(light_dir+view_dir); float spec = pow(max(dot(halfway_dir, normal), 0.0), 64.0); vec3 specular = spec*color; float shadow = calculate_shadow(); vec3 lighting = ambient+((diffuse+specular)*(1.0-shadow)*light_color); float gamma = 2.2; lighting = pow(lighting, vec3(1.0/gamma)); frag_color = vec4(lighting, 1.0); }