#version 430 core
/*
* Copyright 2010 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;
layout(location = 1) out vec4 color;

uniform vec3 camera_world;

uniform vec3 materialCoefficients; // x = ambient, y = diffuse, z = specular 
uniform float specularAlpha;
uniform sampler2D diffuseTexture;
uniform float brightness;
uniform float levels;
uniform sampler2D normalMap;
uniform bool normalMapping;


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

uniform struct PointLight {
	vec3 color;
	vec3 position;
	vec3 attenuation;
} pointL;

vec3 cel(vec3 n, vec3 l, vec3 v, vec3 diffuseC, float diffuseF, vec3 specularC, float specularF, float alpha, bool attenuate, vec3 attenuation, float levels) {
	l = normalize(l);
	float NdotL = dot(n, l);
	float d = length(l);
	
	float _levels = floor(levels);
	float scaleFactor = 1.0f/_levels;
	float att = 1.0;
	if(attenuate) att = 1.0f / (attenuation.x + d * attenuation.y + d * d * attenuation.z);
	vec3 r = reflect(-l, n);
	
	vec3 diffuse = (diffuseC * diffuseF) * floor(max(NdotL, 0)* _levels)*scaleFactor;
	
	float specMask;
	if(pow(dot(r, v), alpha) > 0.6)
		specMask = 1.0f;
	else specMask = 0.0f;
	
	//vec3 spec = vec3(0);
	float spec = 0.0f;
	if(NdotL > 0.0)	 
		 spec = specularF * pow(max(0, dot(r, v)), alpha) * specMask;
	
	return diffuse + spec;
}

vec3 normalTex(vec3 normal, vec3 position){
	vec3 n;
	n.x = normal.x;
	n.y = normal.y;
	n.z = normal.z;
	n = n * 0.5 + 0.5;
	
	//vec3 col;
	//col.x = normal.x;
	//col.y = normal.y;
	//col.z = log(normal.z);
	return n;
}

void main() {	

	//cel shading texture///
	vec3 texColor = texture(diffuseTexture, vert.uv).rgb;
	
	
	vec3 n = normalize(vert.normal_world);
	vec3 v = normalize(camera_world - vert.position_world);
	
	if(normalMapping)
	{
		vec3 normalTexture = texture(normalMap, vert.uv).rgb;
		vec3 normal = normalize(normalTexture * 2.0f - 1.0f);
		n = normalize(n + normal);
	}
	
	vec4 celTexture;	
	celTexture = vec4(texColor * materialCoefficients.x, 1);
	//color.rgb += spec + diffuse;
	
	celTexture.rgb += cel(n, pointL.position - vert.position_world, v, pointL.color * texColor, materialCoefficients.y, pointL.color, materialCoefficients.z, specularAlpha, true, pointL.attenuation, levels);

	celTexture.rgb += cel(n, -dirL.direction, v, dirL.color * texColor, materialCoefficients.y, dirL.color, materialCoefficients.z, specularAlpha, false, vec3(0), levels); 
	//float edgeMask = (dot(v, n) > 0.2) ? 1 : 0;
	
	//color.rgb = edgeMask * color.rgb;
	//celTexture.rgb += cel(n, pointL.position - vert.position_world, v, pointL.color * texColor, materialCoefficients.y, pointL.color, materialCoefficients.z, specularAlpha, true, pointL.attenuation, levels)+cel(n, -dirL.direction, v, dirL.color * texColor, materialCoefficients.y, dirL.color, materialCoefficients.z, specularAlpha, false, vec3(0), levels); 
	
	
	//normal texture///
	
	vec4 normalTexture;
	normalTexture = vec4(normalTex(vert.normal_world, vert.position_world), 1.0);
	
	gl_FragData[0] = celTexture *= brightness;
	gl_FragData[1] = normalTexture;
	
	
}

