
layout(location = 0, index = 0) out vec4 outcol0;

uniform vec4 diffcol;

in vec3 ws_norm;
in vec3 ws_lightvec;
in vec3 ws_viewvec;

/*
//http://www.popekim.com/2011/11/optimized-oren-nayar-approximation.html
half ComputeOrenNayarLighting_Fakey( half3 N, half3 L, half3 V, half roughness )
{
  // Through brute force iteration I found this approximation. Time to test it out.
  half LdotN = dot( L, N );
  half VdotN = dot( V, N );
  half result = saturate(LdotN);
  half soft_rim = saturate(1-VdotN/2); //soft view dependant rim
  half fakey = pow(1-result*soft_rim,2);//modulate lambertian by rim lighting
  half fakey_magic = 0.62;
  //(1-fakey)*fakey_magic to invert and scale down the lighting
  fakey = fakey_magic - fakey*fakey_magic;
  return lerp( result, fakey, roughness );
}
*/

// http://content.gpwiki.org/index.php/D3DBook:(Lighting)_Oren-Nayar
// http://fgiesen.wordpress.com/2010/10/21/finish-your-derivations-please/
float oren_nayar( vec3 v, vec3 n, vec3 l, float roughness )
{

	// Compute the other aliases
	float gamma   = dot ( v - n * dot( v, n ), 
						  l - n * dot( l, n ) );

	float rough_sq = roughness * roughness;
	float A = 1.0 - 0.5 * (rough_sq / (rough_sq + 0.57));
	float B = 0.45 * (rough_sq / (rough_sq + 0.09));

	float vdotn = dot(v, n);
	float ldotn = dot(l, n);
	float C = sqrt((1.0 - vdotn*vdotn) * (1.0 - ldotn*ldotn)) / max(vdotn, ldotn);

	float final = (A + B * max( 0.0, gamma ) * C);

	return max( 0.0, dot( n, l ) ) * final;
}

float lambert( vec3 n, vec3 l )
{
	return dot( n, l );
}

void main()
{
	//float n_dot_l = dot( normalize(ws_norm), normalize(ws_lightvec) );
	//float its = lambert( normalize( ws_norm ), normalize( ws_lightvec ) );
	const float roughness = 0.1;
	float its = oren_nayar( normalize( ws_viewvec ), normalize( ws_norm ), normalize( ws_lightvec ), roughness );

	outcol0 = vec4( diffcol.rgb * its, diffcol.a );
}
