#version 460 core
in vec4 col;
in vec2 texCoord;
in vec3 Normal;
in vec3 fragPos;
out vec4 color;
// Should be same as Utilities.h header file
const int MAX_POINT_LIGHTS = 3;
const int MAX_SPOT_LIGHTS = 3;
struct Light {
vec3 colour;
float ambientIntensity;
float diffuseIntensity;
};
struct DirectionalLight {
Light base;
vec3 direction;
};
struct PointLight {
Light base;
vec3 position;
float constant;
float linear;
float exponent;
};
struct SpotLight {
PointLight base;
vec3 direction;
float edge;
};
struct Material {
float specularIntensity;
float shininess;
};
uniform int pointLightCount;
uniform int spotLightCount;
// Lights
uniform DirectionalLight directionalLight;
uniform PointLight pointLight[MAX_POINT_LIGHTS];
uniform SpotLight spotLight[MAX_SPOT_LIGHTS];
// Textures
uniform sampler2D theTexture;
// Materials
uniform Material material;
// Eye Position
uniform vec3 eyePosition;
vec4 calcLightByDirection(Light light, vec3 direction) {
// Ambient Light
vec4 ambientColour = vec4(light.colour, 1.0f) * light.ambientIntensity;
// Diffuse Light
// Getting the cosine of angle between two vectors
float diffuseFactor = max(dot(normalize(Normal), normalize(direction)), 0.0f);
vec4 diffuseColour = vec4(light.colour * light.diffuseIntensity * diffuseFactor, 1.0f);
// Specular Light
vec4 specularColour = vec4(0, 0, 0, 0);
// If no diffuse, then no specular
if(diffuseFactor > 0.0f) {
vec3 fragToEye = normalize(eyePosition - fragPos);
vec3 reflectedVertex = normalize(reflect(direction, normalize(Normal)));
float specularFactor = dot(fragToEye, reflectedVertex);
if(specularFactor > 0.0f) {
specularFactor = pow(specularFactor, material.shininess);
specularColour = vec4(light.colour * material.specularIntensity * specularFactor, 1.0f);
}
}
return (ambientColour + diffuseColour + specularColour);
}
vec4 calcDirectionalLight() {
return calcLightByDirection(directionalLight.base, directionalLight.direction);
}
vec4 calcPointLightsBase(PointLight pLight) {
// Calculating Direction of our Point Lights
// Getting direction from light to fragment
vec3 direction = fragPos - pLight.position;
float distance = length(direction);
direction = normalize(direction);
vec4 colour = calcLightByDirection(pLight.base, direction);
float attenuation = pLight.exponent * distance * distance +
pLight.linear * distance +
pLight.constant;
return (colour / attenuation);
}
vec4 calcSpotLightsBase(SpotLight sLight) {
// Getting Direction
vec3 rayDirection = normalize(fragPos - sLight.base.position);
float slFactor = dot(rayDirection, sLight.direction);
// If we are withing range
if(slFactor > sLight.edge) {
vec4 colour = calcPointLightsBase(sLight.base);
return colour * (1.0f - (1.0 - slFactor) * (1.0f/(1.0f - sLight.edge)));
}
else {
return vec4(0, 0, 0, 0);
}
}
vec4 calcPointLights() {
vec4 totalColour = vec4(0, 0, 0, 0);
for(int i = 0; i < pointLightCount; i++) {
totalColour += calcPointLightsBase(pointLight[i]);
}
return totalColour;
}
vec4 calcSpotLights() {
vec4 totalColour = vec4(0, 0, 0, 0);
for(int i = 0; i < spotLightCount; i++) {
totalColour += calcSpotLightsBase(spotLight[i]);
}
return totalColour;
}
void main() {
vec4 finalColour = calcDirectionalLight();
finalColour += calcPointLights();
finalColour += calcSpotLights();
color = texture(theTexture, texCoord) * finalColour;
}