#version 330 core

layout(location = 0) out vec4 f_color;

in vec3 v_normal;
in vec3 v_position;
in vec2 v_tex_coord;

struct Material {
 vec3 ambient; //Farbe bei Umgebungslicht
 vec3 diffuse; //Farbe von diffusen Oberflaechen
 vec3 specular; //Farbe von Reflexionen
 vec3 emissive; //selbst leuchtendes
 float shininess; //Staerke der Reflexion
 int texturflag;
};

struct DirectionalLight { //Richtungslicht, z.B. Sonne
 vec3 direction; //Richtung in die das Licht scheint
 vec3 diffuse;
 vec3 specular;
 vec3 ambient;
};

struct PointLight {
 vec3 position;
 vec3 diffuse;
 vec3 specular;
 vec3 ambient;
 float linear;
 float quadratic;
};

struct SpotLight {
 vec3 position;
 vec3 direction; // Must be a normalized vector
 float innerCone;
 float outerCone;
 vec3 diffuse;
 vec3 specular;
 vec3 ambient;
};

uniform Material u_material;
uniform float u_alpha=1.0f; //Durchsichtigkeit: 1.0=undurchsichtig, 0.0=voellig durchsichtig
uniform DirectionalLight u_directional_light;
uniform PointLight u_point_light;
uniform SpotLight u_spot_light;
uniform SpotLight u_spot_light2;
uniform sampler2D u_diffuse_map;

void main()
{
 vec3 view = normalize(-v_position);
 vec3 normal = normalize(v_normal);

 //Textur:
 vec3 diffuseColor;
 vec3 ambientColor;
 if(u_material.texturflag != 0)
  {
   vec4 texColor4 = texture(u_diffuse_map, v_tex_coord);
   if(texColor4.w < 0.9) {discard;} //durchsichtige Pixel nicht zeichnen
   //diffuseColor = u_material.diffuse * texColor4.xyz;//test
   //ambientColor = u_material.ambient * texColor4.xyz;//test
   //ambientColor = u_material.ambient * diffuseColor;//test
   diffuseColor = texColor4.xyz;
   ambientColor = texColor4.xyz;
  }
 else
  {
   diffuseColor = u_material.diffuse;
   ambientColor = u_material.ambient;
  }
 
 //Richtungslicht:
 float dd=0.0001;
 vec3 light = normalize(-u_directional_light.direction); //Richtung aus der das Licht kommt
 vec3 reflection = reflect(-light, normal);
 vec3 ambient = u_directional_light.ambient * ambientColor;
 vec3 diffuse = u_directional_light.diffuse * max(dot(normal, light), 0.0) * diffuseColor;
 vec3 specular = u_directional_light.specular * pow(max(dot(reflection, view), dd), u_material.shininess) * u_material.specular;

 //Punktlicht:
 light = normalize(u_point_light.position - v_position);
 reflection = reflect(-light, normal);
 float distance = length(u_point_light.position - v_position);
 float attenuation = 1.0 / ((1.0) + (u_point_light.linear*distance) + (u_point_light.quadratic*distance*distance));
 ambient += attenuation * u_point_light.ambient * ambientColor;
 diffuse += attenuation * u_point_light.diffuse * max(dot(normal, light), 0.0) * diffuseColor;
 specular += attenuation * u_point_light.specular * pow(max(dot(reflection, view), dd), u_material.shininess) * u_material.specular;

 //Spotlicht:
 light = normalize(u_spot_light.position - v_position);
 reflection = reflect(-light, normal);
 float theta = dot(light, u_spot_light.direction);
 float epsilon = u_spot_light.innerCone - u_spot_light.outerCone;
 float intensity = clamp((theta - u_spot_light.outerCone) / epsilon, 0.0f, 1.0f);
 if(theta > u_spot_light.outerCone) {
   ambient += u_spot_light.ambient * ambientColor;
   diffuse += intensity * u_spot_light.diffuse * max(dot(normal, light), 0.0) * diffuseColor;
   specular += intensity * u_spot_light.specular * pow(max(dot(reflection, view), dd), u_material.shininess) * u_material.specular;
 } else {
   ambient += u_spot_light.ambient * ambientColor;
 }

 //Leuchtturm-Spotlicht:
 light = normalize(u_spot_light2.position - v_position);
 theta = dot(light, u_spot_light2.direction);
 if(theta > u_spot_light2.outerCone) {
   reflection = reflect(-light, normal);
   epsilon = u_spot_light2.innerCone - u_spot_light2.outerCone;
   intensity = clamp((theta - u_spot_light2.outerCone) / epsilon, 0.0f, 1.0f);
   ambient += u_spot_light2.ambient * ambientColor;
   diffuse += intensity * u_spot_light2.diffuse * max(dot(normal, light), 0.0) * diffuseColor;
   specular += intensity * u_spot_light2.specular * pow(max(dot(reflection, view), dd), u_material.shininess) * u_material.specular;
 }

 f_color = vec4(ambient + diffuse + specular + u_material.emissive, u_alpha);
}
