#version 430 struct Fragment { vec3 position; vec3 normal; vec4 material; }; struct Light { vec3 position; vec3 power; // x = ambient, y = diffuse, z = specular vec3 ambient; vec3 diffuse; vec3 specular; vec3 fade; // x = constant, y = linear, z = quadratic }; in Fragment fragment; #define MAX_LIGHTS 16 layout(location = 4) uniform vec3 eye_position; layout(location = 5) uniform uint num_lights; layout(location = 6) uniform Light lights[MAX_LIGHTS]; out vec4 frag_color; void main() { vec3 accumulator = vec3(0.0); vec3 normal = normalize(fragment.normal); for (uint i = 0; i < MAX_LIGHTS && i < num_lights; ++i) { vec3 to_eye = eye_position - fragment.position; vec3 to_light = lights[i].position - fragment.position; float dist = length(to_light); vec3 to_light_norm = to_light / dist; // normalize(to_light); vec3 reflected = reflect(-to_light_norm, normal); float fade = lights[i].fade.x + lights[i].fade.y * dist + lights[i].fade.z * dist * dist; // Multipliers // a = ambient, d = diffuse, s = specular float a = lights[i].power.x * fragment.material.x / fade; float d = lights[i].power.y * fragment.material.y / fade * clamp(dot(to_light_norm, normal), 0.0, 1.0); float s = lights[i].power.z * fragment.material.z / fade * pow(clamp(dot(reflected, normal), 0.0, 1.0), clamp(fragment.material.w, 1.0, 1000.0)); // Seems like weird things happen if w is set to 0 and not clamped (maybe it is not exactly 0) vec3 color = a * lights[i].ambient + d * lights[i].diffuse + s * lights[i].specular; accumulator += color; } frag_color = vec4(accumulator, 1.0); }