#ifndef __PHONG_TOOLS__HLSL__
#define __PHONG_TOOLS__HLSL__

//////////////////////////////////////////////////////////////////////////
/// Includes
//////////////////////////////////////////////////////////////////////////
#include "Uniforms.hlsl"

//////////////////////////////////////////////////////////////////////////
// Retrieves SH lighting
//////////////////////////////////////////////////////////////////////////
float3 ComputeAmbientLighting(float3 vWS_Normal)
{
    return ComputeDiffuseSH(vWS_Normal);
}

//////////////////////////////////////////////////////////////////////////
// Retrieves LIT
//////////////////////////////////////////////////////////////////////////
half4 myLit(float NdotL, float RdotL, float Exp)
{
    half4 vLit = 0;
    vLit.y = NdotL;
    if (NdotL > 0)
        vLit.z = pow(RdotL, Exp);
    return vLit;
}

//////////////////////////////////////////////////////////////////////////
// Gets Diffuse And spec lighting with a specified light direction for specular
//////////////////////////////////////////////////////////////////////////
void ComputeDiffuseAndSpecialSpecularLighting(out float3 vDiffuseLighting, out float3 vSpecularLighting, float NdotL, float3 vReflectedEye, float fShininessFactor, float3 vLightDir)
{
    float RdotL = saturate(dot(vReflectedEye, vLightDir));
    half4 vLit = myLit(NdotL, RdotL, fShininessFactor);

    vDiffuseLighting  = vLit.y * LightColor.rgb;
    vSpecularLighting = NdotL * vLit.z * LightColor.rgb;
}

//////////////////////////////////////////////////////////////////////////
// Gets Diffuse And spec lighting
//////////////////////////////////////////////////////////////////////////
void ComputeDiffuseAndSpecularLighting(out float3 vDiffuseLighting, out float3 vSpecularLighting, float NdotL, float3 vReflectedEye, float fShininessFactor)
{
    ComputeDiffuseAndSpecialSpecularLighting(vDiffuseLighting, vSpecularLighting, NdotL, vReflectedEye, fShininessFactor, -LightDir);
}

//////////////////////////////////////////////////////////////////////////
// Gets only Diffuse
//////////////////////////////////////////////////////////////////////////
void ComputeDiffuseLighting(out float3 vDiffuseLighting, float NdotL)
{
    vDiffuseLighting  = NdotL * LightColor.rgb;
}

//////////////////////////////////////////////////////////////////////////
// Get Filter
//////////////////////////////////////////////////////////////////////////
void ComputeFresnelCrossFilter(out float3 vFilter, float3 vBaseSampler, float RdotL, float EdotN)
{
	static const float FresnelRepartition = 0.6;
    static const float FresnelShininess = 0.65;
	static const float FresnelStrength = 0.17f;

#if 0
    float fLuminance = (1/dot(vBaseSampler, float3(0.333333f,0.333333f,0.333333f)));
	vFilter = saturate(fLuminance *  vBaseSampler);
#else
    // Use YCoCg for colorization to have control on luminance and color saturation
    static const float SpecLuminance = 1.0;
    static const float SpecSaturation = 3.0;

    float3 vRGBToY  = float3( 0.25, 0.5 , 0.25);
    float3 vRGBToCo = SpecSaturation*float3( 0.5,  0.  ,-0.5);
    float3 vRGBToCg = SpecSaturation*float3(-0.25, 0.5, -0.25);

    float3 vYCoCgToR  = float3( 1,  1, -1);
    float3 vYCoCgToG  = float3( 1,  0,  1);
    float3 vYCoCgToB  = float3( 1, -1, -1);

    float3 vColor_YCoCg = float3(SpecLuminance, // We want to ignore luminance to have specular even on black textures
                                 dot(vRGBToCo, vBaseSampler), 
                                 dot(vRGBToCg, vBaseSampler));

    vFilter     = 		 float3((dot(vYCoCgToR,  vColor_YCoCg)),
                                (dot(vYCoCgToG,  vColor_YCoCg)),
                                (dot(vYCoCgToB,  vColor_YCoCg)));
#endif

	RdotL = saturate(FresnelRepartition+(1-FresnelRepartition)*saturate(RdotL));
    float fFresnel = RdotL*pow(1-saturate(EdotN),1+2*FresnelShininess);
	
	vFilter = FresnelStrength * fFresnel * vFilter;
}

#endif // __PHONG_TOOLS__HLSL__
