#version 430 core
/*
* Copyright 2019 Vienna University of Technology.
* Institute of Computer Graphics and Algorithms.
* This file is part of the ECG Lab Framework and must not be redistributed.
*/

in VertexData {
	vec3 position_world;
	vec3 normal_world;
	vec2 uv;
} vert;

out vec4 color;

uniform vec3 camera_world;

uniform vec3 materialCoefficients; // x = ambient, y = diffuse, z = specular 
uniform float specularAlpha;
uniform sampler2D diffuseTexture;
uniform sampler2D specularTexture;

uniform struct DirectionalLight {
	vec3 color;
	vec3 direction;
} dirL;


/* Parameters for color bands */
const float threshold1 = 0.95;
const float threshold2 = 0.75;
const float threshold3 = 0.50;
const float threshold4 = 0.25;

const float color1 = 1.0;
const float color2 = 0.8;
const float color3 = 0.6;
const float color4 = 0.4;
const float color5 = 0.2;

/* threshold value for blending color bands. Bigger values create bigger gradients */
const float eps = 0.01;

vec3 cel(vec3 n, vec3 l, vec3 v, vec3 diffuseC, float diffuseF, vec3 specularC, float specularF, float alpha){

	// diffuse
	float intensity = max(0.0, dot(normalize(l), n));
	float df;

    if (intensity > threshold1 + eps)      df = color1;
    else if (intensity > threshold1 - eps && intensity < threshold1 + eps) df = mix(color2, threshold1, smoothstep(threshold1 - eps, threshold1 + eps, intensity));
    else if (intensity > threshold2 + eps) df = color2;
    else if (intensity > threshold2 - eps && intensity < threshold2 + eps) df = mix(color3, color2, smoothstep(threshold2 - eps, threshold2 + eps, intensity));
    else if (intensity > threshold3 + eps) df = color3;
    else if (intensity > threshold3 - eps && intensity < threshold3 + eps) df = mix(color4, color3, smoothstep(threshold3 - eps, threshold3 + eps, intensity));
    else if (intensity > threshold4 + eps) df = color4;
    else if (intensity > threshold4 - eps && intensity < threshold4 + eps) df = mix(color5, color4, smoothstep(threshold4 - eps, threshold4 + eps, intensity));
    else df = color5;


	vec3 diffuseColor = diffuseC * diffuseF * df;

	//specular
    vec3 lightDir = normalize(l);
    vec3 reflectDir = reflect(-lightDir, n);
    float spec = pow(max(dot(v, reflectDir), 0.0), alpha);

	vec3 specularColor = spec * specularC * specularF;

	return diffuseColor + specularColor;
}

void main(void) {

	vec3 n = normalize(vert.normal_world);
	vec3 v = normalize(camera_world - vert.position_world);

	vec3 texColor = texture(diffuseTexture, vert.uv).rgb;

	color = vec4(texColor * materialCoefficients.x, 1); // ambient

	vec3 specularTexColor = texture(specularTexture, vert.uv).rgb;
	
	//directional light contribution
	color.rgb += cel(n, -dirL.direction, v, dirL.color * texColor, materialCoefficients.y, dirL.color * specularTexColor, materialCoefficients.z, specularAlpha);

	//point light contribution
	color.rgb += cel(n, pointL.position - vert.position_world, v, pointL.color * texColor, materialCoefficients.y, pointL.color, materialCoefficients.z, specularAlpha);

}