#version 330 core in vec4 v_normal; in vec4 color; in vec3 light_direction; in vec4 v_light_space_position; // New: Position transformed by LightSpaceMatrix uniform int render_normals_bool; uniform int render_shadows_bool; uniform sampler2D shadow_map; // New: Depth map texture out vec4 FragColor; const float ambient_strenght = 0.3; const float diffuse_strenght = 0.7; /** * Calculates the shadow factor (0.0 for shadow, 1.0 for lit). */ float calculate_shadow() { float min_bias = 0.003; float max_bias = 0.01; float dot_product = dot(normalize(v_normal.xyz), normalize(light_direction)); float bias = max(max_bias * (1.0 - dot_product), min_bias); // float bias = 0; // 1. Perspective divide to get Normalized Device Coordinates (NDC) vec3 proj_coords = v_light_space_position.xyz / v_light_space_position.w; // 2. Transform to texture coordinates (0 to 1 range) vec2 tex_coords = proj_coords.xy * 0.5 + 0.5; // 3. Get the closest depth from the light's perspective (shadow map) // We sample the red channel since Macroquad's depth texture stores depth data there. float closest_depth = texture(shadow_map, tex_coords).r; // 4. Get the current fragment's depth from the light's perspective // float current_depth = proj_coords.z; float current_depth = proj_coords.z * 0.5 + 0.5; // float current_depth = v_light_space_position.z; // 5. Check if the fragment is outside the light frustum if (tex_coords.x > 1.0 || tex_coords.x < 0.0 || tex_coords.y > 1.0 || tex_coords.y < 0.0 || current_depth > 1.0) { return 1.0; } // float shadow = 0.0; // vec2 texelSize = 1.0 / textureSize(shadow_map, 0); // int x_ran = 1; // for (int x = -x_ran; x <= x_ran; x++) // { // for (int y = -x_ran; y <= x_ran; y++) // { // float pcfDepth = texture(shadow_map, tex_coords + vec2(x, y) * texelSize).x; // shadow += current_depth - bias > pcfDepth ? 0.0 : 1.0; // } // } // shadow = current_depth - bias > closest_depth ? 0.0 : 1.0; // shadow /= ((2 * x_ran) + 1) * ((2 * x_ran) + 1); // 6. Compare depths with a bias: if current depth > closest depth, we are in shadow (0.0) float shadow = current_depth - bias > closest_depth ? 0.0 : 1.0; return min(max(shadow, 0), 1); } void main() { float diff = max(dot(normalize(vec3(v_normal.x, v_normal.y, v_normal.z)), normalize(light_direction)), 0) * diffuse_strenght; if (render_normals_bool == 1) { FragColor = vec4(v_normal); return; } if (render_shadows_bool == 1) { float lighting = ambient_strenght + diff; FragColor = normalize(v_normal) * lighting; return; } float shadow_factor = calculate_shadow(); float lighting = ambient_strenght + diff * shadow_factor; FragColor = normalize(abs(v_normal)) * lighting; }