uniform sampler1D Ward; // only used by isotropic Ward model

#define PI 3.14159265

vec3 calculate_ward_isotropic_model(in vec3 n, in vec3 l, in vec3 e, in float shininess)
{
	vec3 hv = normalize(l + e);
	float LdotN = dot(l, n);
	float EdotN = dot(e, n);
	float NdotHV = dot(n, hv);
	float shine_sq = shininess * shininess;

	float exp_a = texture(Ward, NdotHV*0.5 + 0.5).r;

	float spec_numer = exp(exp_a/shine_sq);
	float spec_denom = 4.0 * PI * shine_sq * sqrt(LdotN*EdotN);
	float specTerm = spec_numer / spec_denom;

	float diffTerm = max(LdotN, 0.0);

	return vec3(diffTerm, specTerm, 1.0);
}


vec3 calculate_ward_anisotropic_model(in vec3 n, in vec3 l, in vec3 e, in vec2 shininess)
{
	// coordinate frame
	vec3 t = cross(n, vec3(1.0, 0.0, 0.0));
	vec3 b = cross(n, t);

	vec3 hv = normalize(l + e);
	float LdotN = dot(l, n);
	float EdotN = dot(e, n);
	float NdotHV = dot(n, hv);
	float TdotHV = dot(n, t);
	float BdotHV = dot(n, b);

	float diffTerm = max(LdotN, 0.0);

	float beta_a = TdotHV / shininess.x;
	beta_a *= beta_a;

	float beta_b = BdotHV / shininess.y;
	beta_b *= beta_b;

	float beta = -2.0 * (beta_a + beta_b) / (1.01 + NdotHV);

	float spec_denom = 4.0 * PI * shininess.x * shininess.y * sqrt(LdotN * EdotN);
	float specTerm = exp(beta) / spec_denom;
	float fresTerm = pow(1.0 - dot(e, hv), 5.0)*0.5;
	return vec3(diffTerm, specTerm, fresTerm);
}

#undef PI
