#version 450

layout(location = 0) in vec4 tes_normal;
layout(location = 1) in vec4 tes_uv;
layout(location = 2) in vec4 v_eye_dir;
layout(location = 3) in vec4 v_light_dir;

layout (binding = 1) uniform sampler2D tex_diffuse;
layout (binding = 2) uniform sampler2D tex_normal;

layout (location = 0) out vec4 FragColor;


layout (std140, binding = 0) uniform uniforms_t
{ 
  mat4 ProjectionMatrix;
  mat4 ViewMatrix;
  mat4 ModelMatrix;
  vec4 uv_tiling;
  vec4 light_position;
  vec4 tess_params;
} ub;




// http://www.thetenthplanet.de/archives/1180
mat3 cotangent_frame(vec3 N, vec3 p, vec2 uv)
{
    // get edge vectors of the pixel triangle
    vec3 dp1 = dFdx( p );
    vec3 dp2 = dFdy( p );
    vec2 duv1 = dFdx( uv );
    vec2 duv2 = dFdy( uv );
 
    // solve the linear system
    vec3 dp2perp = cross( dp2, N );
    vec3 dp1perp = cross( N, dp1 );
    vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
    vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
 
    // construct a scale-invariant frame 
    float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );
    return mat3( T * invmax, B * invmax, N );
}

vec3 perturb_normal(vec3 N, vec3 V, vec2 texcoord)
{
    // assume N, the interpolated vertex normal and 
    // V, the view vector (vertex to eye)
   vec3 map = texture(tex_normal, texcoord ).xyz;
   map = map * 255./127. - 128./127.;
   mat3 TBN = cotangent_frame(N, -V, texcoord);
   return normalize(TBN * map);
}





void main()
{
  vec2 uv = tes_uv.xy;
  //uv.y = 1.0 - uv.y;
  
  vec3 c0 = texture(tex_diffuse, uv).rgb;

  vec3 N = normalize(tes_normal.xyz);
  vec3 E = normalize(v_eye_dir.xyz);
  vec3 L = normalize(v_light_dir.xyz);  
  //L.y *= -1.0; 
  vec3 PN = perturb_normal(N, E, uv);
 
  
  vec3 fc = vec3(0.0, 0.0, 0.0);
  
  vec3 la0 = vec3(0.2, 0.2, 0.2);
  vec3 ld0 = vec3(0.9, 0.85, 0.8);
  vec3 ls0 = vec3(0.9, 0.9, 0.9);
  vec3 mA = vec3(0.8, 0.8, 0.8);
  vec3 mD = vec3(0.9, 0.9, 0.9);
  vec3 mS = vec3(0.4, 0.4, 0.4);
  float mSpecExp = 16.0;  
  
  fc += (la0 * mA) * c0.rgb;
  float lambert = dot(PN, L);
  if (lambert > 0)
  {
    fc += ld0 * mD * lambert * c0;
    
    vec3 R = reflect(-L, PN);
    float specular = pow(abs(dot(R, E)), mSpecExp);
    fc += ls0 * mS * specular;	
  } 
  
  FragColor = vec4(fc, 1.0);
}
