#version 330 core struct TextureArray { sampler2D texture_diffuse[32]; // Array of diffuse textures // Add more texture types if needed }; uniform TextureArray uTextures; // Array of textures uniform int uNumDiffuseTextures; // Number of active diffuse textures uniform mat4 uLightSpaceMatrix; // Light space matrix uniform sampler2D uShadowMap; // Shadow map texture in vec2 TexCoord; // From vertex shader in vec3 Normal; // From vertex shader in vec3 FragPos; // From vertex shader in vec4 FragPosLightSpace; // From vertex shader out vec4 FragColor; // Final fragment color // Lighting parameters struct Light { vec3 direction; vec3 position; }; uniform Light light; uniform vec3 viewPos; // Position of the camera/viewer float ShadowCalculation(vec4 fragPosLightSpace) { // Perform perspective divide vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; // Transform to [0,1] range projCoords = projCoords * 0.5 + 0.5; // Get closest depth value from light's perspective float closestDepth = texture(uShadowMap, projCoords.xy).r; // Get current fragment's depth float currentDepth = projCoords.z; // Check whether current frag pos is in shadow float bias = 0.005; float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; // Keep the shadow at 0.0 when outside the far plane region of the light's orthographic projection if(projCoords.z > 1.0) shadow = 0.0; return shadow; } void main() { // Normalize the normal vector vec3 norm = normalize(Normal); // Calculate the direction from the fragment to the light vec3 lightDir = normalize(light.direction); // Compute the diffuse intensity float diff = max(dot(norm, lightDir), 0.0); // Initialize diffuse color vec4 diffuseColor = vec4(0.0); // Sample and accumulate diffuse textures for(int i = 0; i < uNumDiffuseTextures; ++i) { diffuseColor += texture(uTextures.texture_diffuse[i], TexCoord); } // Apply the diffuse intensity diffuseColor *= diff; // Simple ambient lighting vec3 ambient = 0.1 * diffuseColor.rgb; // Calculate shadow float shadow = ShadowCalculation(FragPosLightSpace); // Final color combining ambient and shadowed diffuse components vec3 lighting = ambient + (1.0 - shadow) * diffuseColor.rgb; FragColor = vec4(lighting, diffuseColor.a); }