#include "RTCommonData.fxh"


//----------------------- Cel-shading parameters ---------------------//
float g_fSilouhetteThreshold = 0.2;					// The threshold which determines if we're on a silouhette or not
bool g_bBacklightEmulation = false;					// A enabler for a lighting trick avoiding unlit pixels
float g_fNbShades = 2.0;							// The default number of shades
float3 g_vBaseColor = float3(1.0, 1.0, 1.0);		// The base color from which we create the shades


//--------------------------------------------------------------------------------------
// SHADERS BODIES
//--------------------------------------------------------------------------------------
void Dot3CelShadingVS(	float4 Pos				: POSITION,
						float3 Normal			: NORMAL,
						float2 Tex				: TEXCOORD0,
						out float4 oPos			: POSITION,
						out float3 oViewNormal	: TEXCOORD0,
						out float3 oViewPos		: TEXCOORD1,
						out float3 oViewVect	: TEXCOORD2,
						out float3 oWorldNormal : TEXCOORD3,
						out float oColorScale	: TEXCOORD4)
{
	//----------- Computation for MRT rendering -----------//
    // Output screen space position
    oViewPos = mul(Pos, g_mWorldView);
    oPos = mul(float4(oViewPos, 1.0f), g_mProj);

    // Transform normal to view space
    oViewNormal = mul(Normal, (float3x3)g_mWorldView);
    
	//----------- Computation for Cel-shading -----------//
	float3 vWorldPos = mul(Pos, g_mWorld);
	oViewVect = normalize(g_vEyeWorldPos - vWorldPos);
	
	oWorldNormal = mul(Normal, g_mWorld);
	oColorScale = dot(normalize(oWorldNormal), normalize(g_vLightVect));    
}


void Dot3CelShadingPS(	float3 ViewNormal	: TEXCOORD0,
						float3 ViewPos		: TEXCOORD1,
						float3 ViewVect		: TEXCOORD2,
						float3 WorldNormal	: TEXCOORD3,
						float ColorScale	: TEXCOORD4,
						out float4 oCol		: COLOR0,
						out float4 oNormal	: COLOR1,
						out float4 oPos		: COLOR2 )
{
	//----------- Computation for Cel-shading -----------//
	float scaleFactor = dot(WorldNormal, ViewVect);
	
	// The color truncation mechanism
	int nScaleFactor = floor(ColorScale * g_fNbShades);	// Find the shade number where the pixel is (even the negative ones :P)
	ColorScale = nScaleFactor / g_fNbShades;				// Compute the scalar to use when deriving g_vBaseColor
	
	// "Backlight" Emulation
	if(g_bBacklightEmulation)
	{
		// 0<=colorScale<(1.0/fNbShades) is the last non-black color band
		// So, if we're under 0.0, we give colorScale the 0 value to blend unlit part with the last shade band
		if(ColorScale < 0.0) ColorScale = 0.0;
	}

	// Blending color value with diffuse texture (if any)
	// Adding one shade to actually have a shade of "white"
	oCol = float4(saturate( (g_vBaseColor * ColorScale) + (g_vBaseColor / g_fNbShades) ), 1.0);	
    
   //----------- MRT outputs for post processing -----------//
    // Output normal
    oNormal = float4(normalize(ViewNormal), 1.0f);
    
    // Output view position
    oPos = float4(ViewPos, 1.0f);
}


//-----------------------------------------------------------------------------
// Technique: Dot3CelShading
// Desc: Renders the scene with a DOT3 cel-shading technique
//-----------------------------------------------------------------------------
technique Dot3CelShading
{
    pass p0
    {
		ZEnable = true;
		ZWriteEnable = true;
		AlphaBlendEnable = false;	// TODO : add states block to restore the pieline states after DXUT renders the GUI
		AlphaTestEnable = false;
		
        VertexShader = compile vs_1_1 Dot3CelShadingVS();
        PixelShader = compile ps_2_0 Dot3CelShadingPS();
    }
}