#version 330 core struct Material { sampler2D diffuse; sampler2D specular; float shininess; }; struct Light { vec3 ambient; vec3 diffuse; vec3 specular; vec3 position; }; struct DirectionalLight { vec3 direction; vec3 ambient; vec3 diffuse; vec3 specular; }; struct PointLight { vec3 position; vec3 ambient; vec3 diffuse; vec3 specular; // attentuation factors float kC; float kL; float kQ; }; in vec2 texCoords; in vec3 fragNormal; in vec3 worldPosition; uniform Material material; uniform Light light; uniform DirectionalLight dirLight; uniform PointLight pointLight; uniform vec3 cameraPosition; uniform vec3 lightColor; out vec4 FragColor; void main() { float lightDistance = length(pointLight.position - worldPosition); float attenuationFactor = 1.0 / (pointLight.kC + (pointLight.kL * lightDistance) + (pointLight.kQ * lightDistance * lightDistance)); vec3 ambientLight = attenuationFactor * pointLight.ambient * vec3(texture(material.diffuse, texCoords)); // @note: Diffuse calculations //vec3 lightDir = normalize(light.position - worldPosition); /* @note: an explanation of why the light direction vector is taken from fragment to the light source. Basic LA really, we need to calculate the angle between the direction of the 2 vectors: a. The direction at which light incidents with the fragment b. The normal vector The reason the light direction is taken from the fragment to the light source, is precisely so we can calculate the angle between the normal and the direction at which light would hit. This if taken as starting from the light source would actually be incorrect, since we would be calculating the angle between the light source in the direction of the fragment and the normal. Consider what happens when it is directly above. The angle becomes 180, not 0. This is because the normal moves in the direction opposite to the lights direction if taken this way, which is not what we expect or want. Reversing this, allows us to consider the angle at the point in which light hits the fragment, and the normal vector of the fragment. */ vec3 lightDir = normalize(pointLight.position - worldPosition); float diffuseStrength = max(dot(lightDir, fragNormal), 0.0); vec3 diffuseLight = attenuationFactor * pointLight.diffuse * diffuseStrength * vec3(texture(material.diffuse, texCoords)); // @note: Specular calculations vec3 viewDir = normalize(cameraPosition - worldPosition); vec3 reflectDir = reflect(-lightDir, fragNormal); float specularity = max(dot(viewDir, reflectDir), 0.0); float shinePower = pow(specularity, material.shininess); vec3 specularLight = attenuationFactor * pointLight.specular * shinePower * vec3(texture(material.specular, texCoords)); vec3 color = ambientLight + diffuseLight + specularLight; FragColor = vec4(color, 1.0); }