2025-11-23 18:40:48 +00:00
|
|
|
#version 330 core
|
|
|
|
|
|
|
|
|
|
in vec4 v_normal;
|
|
|
|
|
in vec4 color;
|
2025-11-23 23:43:48 +00:00
|
|
|
in vec3 light_direction;
|
2025-11-28 20:39:09 +00:00
|
|
|
in vec4 v_light_space_position; // New: Position transformed by LightSpaceMatrix
|
|
|
|
|
|
2025-11-23 18:40:48 +00:00
|
|
|
uniform int render_normals_bool;
|
2025-11-28 20:39:09 +00:00
|
|
|
uniform int render_shadows_bool;
|
|
|
|
|
uniform sampler2D shadow_map; // New: Depth map texture
|
2025-11-23 18:40:48 +00:00
|
|
|
|
|
|
|
|
out vec4 FragColor;
|
|
|
|
|
|
|
|
|
|
const float ambient_strenght = 0.3;
|
|
|
|
|
const float diffuse_strenght = 0.7;
|
|
|
|
|
|
2025-11-28 20:39:09 +00:00
|
|
|
/**
|
|
|
|
|
* 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);
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-23 18:40:48 +00:00
|
|
|
void main() {
|
2025-11-23 23:43:48 +00:00
|
|
|
float diff = max(dot(normalize(vec3(v_normal.x, v_normal.y, v_normal.z)), normalize(light_direction)), 0) * diffuse_strenght;
|
2025-11-28 20:39:09 +00:00
|
|
|
|
2025-11-23 18:40:48 +00:00
|
|
|
if (render_normals_bool == 1) {
|
|
|
|
|
FragColor = vec4(v_normal);
|
2025-11-28 20:39:09 +00:00
|
|
|
return;
|
2025-11-23 18:40:48 +00:00
|
|
|
}
|
2025-11-28 20:39:09 +00:00
|
|
|
if (render_shadows_bool == 1) {
|
|
|
|
|
float lighting = ambient_strenght + diff;
|
|
|
|
|
FragColor = normalize(v_normal) * lighting;
|
|
|
|
|
return;
|
2025-11-23 18:40:48 +00:00
|
|
|
}
|
2025-11-28 20:39:09 +00:00
|
|
|
|
|
|
|
|
float shadow_factor = calculate_shadow();
|
|
|
|
|
|
|
|
|
|
float lighting = ambient_strenght + diff * shadow_factor;
|
|
|
|
|
|
|
|
|
|
FragColor = normalize(abs(v_normal)) * lighting;
|
2025-11-23 18:40:48 +00:00
|
|
|
}
|