#version 400

out vec4 FragColor;

in vec3 Position;
in vec2 TexCoord;
in vec3 Normal;

uniform sampler2D diffuseMap;
uniform sampler2D specularMap;

uniform vec3 viewPosition;

uniform vec3 phongAmbient;
uniform vec3 phongDiffuse;
uniform vec3 phongSpecular;
uniform float phongShininess;

uniform vec3 lightPosition;
uniform vec3 lightDirection;
uniform vec3 lightAmbient;
uniform vec3 lightDiffuse;
uniform vec3 lightSpecular;

void main() {
    vec3 diffuseColor = texture(diffuseMap, TexCoord).rgb;
    vec3 specularColor = texture(specularMap, TexCoord).rgb;

    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(-lightDirection);
    vec3 viewDir = normalize(viewPosition - Position);
    vec3 halfwayDir = normalize(lightDir + viewDir);

    vec3 ambient = lightAmbient * (diffuseColor * phongAmbient);

    float diffImpact = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = lightDiffuse * (diffImpact * diffuseColor * phongDiffuse);

    vec3 reflectDir = reflect(-lightDir, norm);
    float effectiveShininess = max(phongShininess, 1.0);
    float spec = pow(max(dot(norm, halfwayDir), 0.0), effectiveShininess);
    vec3 specular = lightSpecular * (spec * specularColor * phongSpecular);

    vec3 result = ambient + diffuse + specular;

    float gamma = 2.2;
    FragColor.rgb = pow(result.rgb, vec3(1.0/gamma));
}