float3 lightDir;

float4x4 g_WorldMatrix : WorldMatrix;
float4x4 g_ViewMatrix : ViewMatrix;
float4x4 g_ProjectionMatrix : ProjectionMatrix;
bool g_HideOutline : HideOutline = false;

texture g_Texture;
sampler2D texSamp = 
sampler_state
{
    texture = g_Texture;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    AddressU = WRAP;
    AddressV = WRAP;
};

struct OutputVS2
{
	float4 pos:POSITION0;
	float depth : TEXCOORD0;
	float3 normal:TEXCOORD1;
	float2 texCoord:TEXCOORD2;
};

OutputVS2 CelVShader(float3 position:POSITION0, float3 norml:NORMAL0, float2 texCoord:TEXCOORD0)
{
	float4x4 WV = mul(g_WorldMatrix, g_ViewMatrix);
	float4x4 WVP = mul(WV, g_ProjectionMatrix);

	OutputVS2 outVS;
	
	outVS.pos = mul(float4(position, 1.0),WVP);
	outVS.depth = outVS.pos.w;
	
	float3 normal = mul(float4(norml, 0.0), g_WorldMatrix).xyz;
	normal = normalize(normal);
	
	outVS.normal = float4(normal, 1.0);
	
	outVS.texCoord = texCoord;
	
	return outVS;
}

OutputVS2 CelOLShader(float3 position:POSITION0, float3 norml:NORMAL0)
{
	float4x4 WV = mul(g_WorldMatrix, g_ViewMatrix);
	float4x4 WVP = mul(WV, g_ProjectionMatrix);

	OutputVS2 outVS;
	
	float3 spos = position + norml*0.05;
	
	float4 wpos = mul(float4(spos, 1.0), WVP);
	float3 normal = mul(float4(norml, 0.0), g_WorldMatrix).xyz;
	normal = normalize(normal);
	
	outVS.pos = wpos;
	outVS.depth = outVS.pos.w;
	outVS.normal = normal;
	outVS.texCoord = float2(0.0, 0.0);
	
	return outVS;
}

struct PSOutput
{
	float4 Color : COLOR0;
	float4 Depth : COLOR1;
	float4 Normal : COLOR2;
};

PSOutput CelPShader(OutputVS2 Input)
{
	PSOutput Output;
	
	float ndotl = dot(-lightDir, Input.normal);
	if(ndotl <= 0.0f) ndotl = 0.1;
	
	if((ndotl <= 0.25) && (ndotl > 0.0)) ndotl = 0.25;
	if((ndotl <= 0.5) && (ndotl > 0.25)) ndotl = 0.5;
	if((ndotl <= 0.75) && (ndotl > 0.5)) ndotl = 0.75;
	if((ndotl <= 1.00) && (ndotl > 0.75)) ndotl = 1.00;

	float4 texelCol = tex2D(texSamp, Input.texCoord);
	float4 invTex = float4((1.0-texelCol.rgb), 1.0);
	Output.Color = float4(ndotl, ndotl, ndotl, 1.0)*texelCol;
	
	Output.Depth.r = Input.depth;
	Output.Depth.gb = 0.0f;
	Output.Depth.a = 1.0f;

	Output.Normal = float4(Input.normal, 1.0f);	
	
	return Output;
}

float4 wirecolor():COLOR
{
	if (g_HideOutline) return float4(0.0f, 0.0f, 0.0f, 0.0f);
	return float4(0.0f, 0.0f, 0.0f, 0.65f);
}

technique CelShade
{
	pass P0
	{	
		vertexShader = compile vs_2_0 CelVShader();
        	pixelShader  = compile ps_2_0 CelPShader();
	}
	pass P1
	{
		vertexShader = compile vs_2_0 CelOLShader();
		pixelShader = compile ps_2_0 wirecolor();
		CullMode = CW;
	}
}

technique CelShade_DoubleSided
{
	pass P0
	{
		CullMode = NONE;
		vertexShader = compile vs_2_0 CelVShader();
        	pixelShader  = compile ps_2_0 CelPShader();
	}
	pass P1
	{
		vertexShader = compile vs_2_0 CelOLShader();
		pixelShader = compile ps_2_0 wirecolor();
		CullMode = CW;
	}
}

technique CelShade_Transparent
{
	pass P0
	{
		AlphaTestEnable = true;
		AlphaBlendEnable = true;
		SrcBlend = srcAlpha;
		DestBlend = InvSrcAlpha;
		AlphaFunc = Greater;
		AlphaRef = 0.0f;
		vertexShader = compile vs_2_0 CelVShader();
        	pixelShader  = compile ps_2_0 CelPShader();
	}
	pass P1
	{
		vertexShader = compile vs_2_0 CelOLShader();
		pixelShader = compile ps_2_0 wirecolor();
		CullMode = CW;
	}
}

technique CelShade_Transparent_DoubleSided
{
	pass P0
	{
		AlphaTestEnable = true;
		AlphaBlendEnable = true;
		SrcBlend = srcAlpha;
		DestBlend = InvSrcAlpha;
		AlphaFunc = Greater;
		AlphaRef = 0.0f;
		CullMode = NONE;
		vertexShader = compile vs_2_0 CelVShader();
        	pixelShader  = compile ps_2_0 CelPShader();
	}
	pass P1
	{
		vertexShader = compile vs_2_0 CelOLShader();
		pixelShader = compile ps_2_0 wirecolor();
		CullMode = CW;
	}
}

technique CelShadeNoOutline
{
	pass P0
	{
		vertexShader = compile vs_2_0 CelVShader();
        	pixelShader  = compile ps_2_0 CelPShader();
	}
}

technique CelShadeNoOutline_DoubleSided
{
	pass P0
	{
		CullMode = NONE;
		vertexShader = compile vs_2_0 CelVShader();
        	pixelShader  = compile ps_2_0 CelPShader();
	}
}

technique CelShadeNoOutline_Transparent
{
	pass P0
	{
		AlphaTestEnable = true;
		AlphaBlendEnable = true;
		SrcBlend = srcAlpha;
		DestBlend = InvSrcAlpha;
		AlphaFunc = Greater;
		AlphaRef = 0.0f;
		vertexShader = compile vs_2_0 CelVShader();
        	pixelShader  = compile ps_2_0 CelPShader();
	}
}

technique CelShadeNoOutline_Transparent_DoubleSided
{
	pass P0
	{
		AlphaTestEnable = true;
		AlphaBlendEnable = true;
		SrcBlend = srcAlpha;
		DestBlend = InvSrcAlpha;
		AlphaFunc = Greater;
		AlphaRef = 0.0f;
		CullMode = NONE;
		vertexShader = compile vs_2_0 CelVShader();
        	pixelShader  = compile ps_2_0 CelPShader();
	}
}