#version 330 // Input vertex attributes (from vertex shader) in vec3 fragPosition; in vec2 fragTexCoord; in vec4 fragColor; in vec3 fragNormal; // Input uniform values uniform sampler2D texture0; uniform vec4 colDiffuse; // Output fragment color out vec4 finalColor; #define MAX_LIGHTS 4 #define LIGHT_DIRECTIONAL 0 #define LIGHT_POINT 1 struct Light { int enabled; int type; vec3 position; vec3 target; vec4 color; }; uniform Light lights[MAX_LIGHTS]; uniform vec4 ambient; uniform vec3 viewPos; void main() { vec4 texelColor = texture(texture0, fragTexCoord); if (texelColor.a < 0.1) discard; vec3 normal = normalize(fragNormal); vec3 viewD = normalize(viewPos - fragPosition); vec3 lightTotal = ambient.rgb; vec3 specularTotal = vec3(0.0); for (int i = 0; i < MAX_LIGHTS; i++) { if (lights[i].enabled == 1) { vec3 lightDir = vec3(0.0); float attenuation = 1.0; if (lights[i].type == LIGHT_DIRECTIONAL) { lightDir = -normalize(lights[i].target - lights[i].position); } else // LIGHT_POINT { vec3 lightVec = lights[i].position - fragPosition; float dist = length(lightVec); lightDir = normalize(lightVec); attenuation = 1.0 / (1.0 + 0.10 * dist + 0.03 * dist * dist); } float NdotL = max(dot(normal, lightDir), 0.0); lightTotal += lights[i].color.rgb * NdotL * attenuation; if (NdotL > 0.0) { vec3 reflectDir = reflect(-lightDir, normal); float spec = pow(max(dot(viewD, reflectDir), 0.0), 16.0); specularTotal += lights[i].color.rgb * spec * attenuation * 0.25; } } } vec4 tint = colDiffuse * fragColor; vec3 result = (texelColor.rgb * tint.rgb) * lightTotal + specularTotal; finalColor = vec4(result, texelColor.a * tint.a); }