uniform sampler2D CookTorrance; // lookup with vec2(NdotL, shininess^2)


float fresnel(in float x, in float ref_at_norm_incidence)
{
	return pow(1.0 - x, 5.0) * (1.0 - ref_at_norm_incidence) + ref_at_norm_incidence;
}


vec3 calculate_cook_torrance_model(in vec3 n, in vec3 l, in vec3 e, in float shininess, in float ref_at_norm_incidence)
{
	vec3 hv = normalize(l + e);
	float NdotL = max(dot(n, l), 0.0);
	float NdotHV = max(dot(n, hv), 0.0);
	float NdotE = max(dot(n, e), 0.0);
	float EdotHV = max(dot(e, hv), 0.0);

	float geo_numer = 2.0 * NdotHV;
	float geo_denom = EdotHV;
	float geo_b = geo_numer * NdotE / geo_denom;
	float geo_c = geo_numer * NdotL / geo_denom;
	float geo = min(min(geo_b, geo_c), 1.0);

	// get roughtness 
	float r = texture(CookTorrance, vec2(NdotHV, shininess*shininess)).r;
	
	// fresnel term
	float f = fresnel(EdotHV, ref_at_norm_incidence);

	// specular term
	float rs_numer = f*geo*r;
	float rs_denom = NdotE * NdotL;
	float specTerm = rs_numer / rs_denom;

	float diffTerm = NdotL;

	return vec3(diffTerm, specTerm, 1.0);
}

