#include "scattering.h"

float4x4	worldviewproj; 
float4x4	viewproj; 
float4x4	worldMatrix;
float4		lightDir;
float4		camPos;

float4		ambient;
float4		specular;
float		SpecularPower;
//float		bumpHeight = 1.0f; //brp hardcoded for now.

texture2D		diffuseTexture;
texture2D		normalTexture;
texture2D		secondDiffuseTexture;


sampler2D diffuseMap = sampler_state
{
    Texture		= (diffuseTexture);
    AddressU	= WRAP;
    AddressV	= WRAP;       
	MinFilter	= ANISOTROPIC;
	MagFilter	= ANISOTROPIC;
	MipFilter	= ANISOTROPIC;
    MIPMAPLODBIAS	= -2.0f;
    MAXMIPLEVEL		= 0;
    MAXANISOTROPY	= 2.0f;
};

sampler2D normalMap = sampler_state
{
    Texture		= (normalTexture);
    AddressU	= WRAP;
    AddressV	= WRAP;       
	MinFilter	= LINEAR;
	MagFilter	= LINEAR;
	MipFilter	= NONE;
    MIPMAPLODBIAS	= -1.0f;
    MAXMIPLEVEL		= 0;
    MAXANISOTROPY	= 1.0f;
};

sampler2D secondDiffuseMap = sampler_state
{
    Texture		= (secondDiffuseTexture);
    AddressU	= WRAP;
    AddressV	= WRAP;       
	MinFilter	= ANISOTROPIC;
	MagFilter	= ANISOTROPIC;
	MipFilter	= ANISOTROPIC;
    MIPMAPLODBIAS	= -2.0f;
    MAXMIPLEVEL		= 0;
    MAXANISOTROPY	= 1.0f;
};


struct VS_OUT
{
	float4	pos			:	POSITION;
	float3	N			:	TEXCOORD0;	
	float2	uvDiff		:	TEXCOORD1;
	float3	T			:	TEXCOORD2; 
	float3	B			:	TEXCOORD3; 
	float	blend		:	TEXCOORD4;
	float2	uvNorm		:	TEXCOORD5;
	float2	uvBlend		:	TEXCOORD6;
	float4	vpos		:	TEXCOORD7;
	float	depth		:	COLOR0;
};

VS_OUT VShader(
	float3	pos		:	POSITION	: register(v0),
	float3	N		:	NORMAL		: register(v1),		
	float2	uv0		:	TEXCOORD0	: register(v2),		//<- Diffuse 
	float3	T		:	TANGENT		: register(v3),		// in object space
	float3	B		:	BINORMAL	: register(v4),		// in object space
	float 	blend	:	BLENDWEIGHT	: register(v5),
	float2	uv1		:	TEXCOORD1	: register(v6),		//<- Bump
	float2	uv2		:	TEXCOORD2	: register(v7)		//<- Lerp
)
{
	VS_OUT Out	= (VS_OUT)0;
	
	Out.pos	= mul(float4(pos, 1), worldviewproj);	
	Out.N = normalize(mul(N, (float3x4)worldMatrix));
	Out.T = normalize(mul(T,	(float3x4)worldMatrix));
	Out.B = normalize(mul(B, (float3x4)worldMatrix));
	
	Out.uvDiff.xy	= uv0;	
	Out.uvNorm.xy	= uv1;
	Out.uvBlend.xy	= uv2;
	Out.blend		= blend;	

	Out.vpos = mul(float4(pos, 1), worldMatrix);	
	Out.depth = Out.pos.z;
					
    return Out;
}


VS_OUT VShaderInstanced(
	float3	pos		:	POSITION	: register(v0),
	float3	N		:	NORMAL		: register(v1),		
	float2	uv0		:	TEXCOORD0	: register(v2),		//<- Diffuse 
	float3	T		:	TANGENT		: register(v3),		// in object space
	float3	B		:	BINORMAL	: register(v4),		// in object space
	float 	blend	:	BLENDWEIGHT	: register(v5),
	float2	uv1		:	TEXCOORD1	: register(v6),		//<- Bump
	float2	uv2		:	TEXCOORD2	: register(v7),		//<- Lerp
	float4 row1			: TEXCOORD3,
	float4 row2			: TEXCOORD4,
	float4 row3			: TEXCOORD5,
	float4 row4			: TEXCOORD6)
{
	VS_OUT Out	= (VS_OUT)0;
	
	float4x4 mWorld = float4x4(row1, row2, row3, row4);
	Out.vpos = mul(mWorld, float4(pos, 1));
	Out.pos = mul(Out.vpos, viewproj);
	Out.N = normalize(mul((float3x4)mWorld, N));
	Out.T = normalize(mul((float3x4)mWorld, T));
	Out.B = normalize(mul((float3x4)mWorld, B));
	
	Out.uvDiff.xy	= uv0;	
	Out.uvNorm.xy	= uv1;
	Out.uvBlend.xy	= uv2;
	Out.blend		= blend;	

	Out.depth = Out.pos.z;
					
    return Out;
}

float4 PShader(
	float3	N		:	TEXCOORD0	: register(v0),
	float2	uvDiff	:	TEXCOORD1	: register(v1),
	float3	T		:	TEXCOORD2	: register(v2),
	float3	B		:	TEXCOORD3	: register(v3),
	float	blend	:	TEXCOORD4	: register(v4),
	float2	uvNorm	:	TEXCOORD5	: register(v5),
	float4	uvBlend	:	TEXCOORD6	: register(v6),
	float4	vpos	:	TEXCOORD7	: register(v7),
	float	depth	:	COLOR0		: register(v8)
	) : COLOR
{
	float4 color			=	tex2D(diffuseMap,	uvDiff.xy);
	float4 bumpVector		=	tex2D(normalMap,	uvNorm.xy);
	float4 colorB			=	tex2D(secondDiffuseMap,	uvBlend.xy);

	float specularFilter = 1; //brp was ... max(0, specularM.g - 0.2);

	float3 bumpNormal	=	bumpVector;
	bumpNormal.xy		=	bumpNormal.xy * 2.0 - 1.0;
	//bumpNormal.z		=	sqrt(1.0 - dot(bumpNormal.xy, bumpNormal.xy));
	//bumpNormal.xy		=	bumpNormal.xy * bumpHeight.xx;
	bumpNormal			=	normalize(bumpNormal);
	bumpNormal.xyz		=	bumpNormal.x * T + bumpNormal.y * B + bumpNormal.z * N;

	float  diff			=	max(0, dot(bumpNormal, lightDir.xyz));

	float3 E			=	normalize(camPos.xyz - vpos.xyz);
	float3 L			=	lightDir.xyz;
	float3 H			=	normalize(E + L);											

	//float spec			=	pow(max(0 , dot(bumpNormal, H)) , SpecularPower);	
	//float specularLevel = 0.2; // brp hardcoded for now

	color.xyz	=	color.xyz * (1 - blend) + colorB.xyz * blend;
	color.xyz	=	color.xyz * (ambient + diff);

	color = Scattering(vpos.xyz, camPos.xyz, lightDir.xyz, color);

	return color;
}


technique Default
{
    pass Pass0
    {    
		FillMode = SOLID;
		Lighting = FALSE;
		Clipping = FALSE;
		CullMode = NONE;
		
		FogEnable	= FALSE;
		FogColor	= 0x00000000;
		FogDensity	= 1.0f;
		FogEnd		= 10000.0f;
		FogStart	= 50.0f;
				
		//Pixel Pipe Render States
		AlphaBlendEnable	= FALSE;
		AlphaRef			= 0x50;
		AlphaTestEnable		= FALSE;
		AlphaFunc			= GREATER;	
					
		ZEnable				= TRUE;
		ZWriteEnable		= TRUE;
		ZFunc				= LESSEQUAL;

		SrcBlend			= SRCALPHA;
		DestBlend			= INVSRCALPHA;
		
		VertexShader = compile vs_2_0 VShader();
		PixelShader  = compile ps_2_0 PShader();	
    }
}

technique Transparent
{
    pass Pass0
    {    
		FillMode = SOLID;

		Lighting	= FALSE;
		Clipping	= FALSE;
		CullMode	= NONE;

		FogEnable	= FALSE;
		FogColor	= 0x00000000;
		FogDensity	= 1.0f;
		FogEnd		= 10000.0f;
		FogStart	= 50.0f;

		AlphaBlendEnable	= TRUE;
		AlphaRef			= 100;
		AlphaTestEnable		= FALSE;		
		AlphaFunc			= GREATER;

		ZEnable				= TRUE;
		ZWriteEnable		= FALSE;
		ZFunc				= LESSEQUAL;

		SrcBlend			= SRCALPHA;
		DestBlend			= INVSRCALPHA;  

		VertexShader = compile vs_2_0 VShader();
		PixelShader  = compile ps_2_0 PShader();
    }

	pass Pass1
    {    
		FillMode	= SOLID;

		Lighting	= FALSE;
		Clipping	= FALSE;
		CullMode	= NONE;

		FogEnable	= FALSE;
		FogColor	= 0x00000000;
		FogDensity	= 1.0f;
		FogEnd		= 10000.0f;
		FogStart	= 50.0f;

		AlphaBlendEnable	= FALSE;
		AlphaRef			= 200;
		AlphaTestEnable		= TRUE;		
		AlphaFunc			= GREATEREQUAL;	

		ZEnable				= TRUE;
		ZWriteEnable		= TRUE;
		ZFunc				= LESSEQUAL;

		SrcBlend			= SRCALPHA;
		DestBlend			= INVSRCALPHA;  

		VertexShader = compile vs_2_0 VShader();
		PixelShader  = compile ps_2_0 PShader();
    }   
}

technique DefaultInstanced
{
    pass Pass0
    {    
		FillMode = SOLID;
		Lighting = FALSE;
		Clipping = FALSE;
		CullMode = NONE;
		
		FogEnable	= FALSE;
		FogColor	= 0x00000000;
		FogDensity	= 1.0f;
		FogEnd		= 10000.0f;
		FogStart	= 50.0f;
				
		//Pixel Pipe Render States
		AlphaBlendEnable	= FALSE;
		AlphaRef			= 0x50;
		AlphaTestEnable		= FALSE;
		AlphaFunc			= GREATER;	
					
		ZEnable				= TRUE;
		ZWriteEnable		= TRUE;
		ZFunc				= LESSEQUAL;

		SrcBlend			= SRCALPHA;
		DestBlend			= INVSRCALPHA;
		
		VertexShader = compile vs_2_0 VShaderInstanced();
		PixelShader  = compile ps_2_0 PShader();	
    }
}

technique TransparentInstanced
{
    pass Pass0
    {    
		FillMode = SOLID;

		Lighting	= FALSE;
		Clipping	= FALSE;
		CullMode	= NONE;

		FogEnable	= FALSE;
		FogColor	= 0x00000000;
		FogDensity	= 1.0f;
		FogEnd		= 10000.0f;
		FogStart	= 50.0f;

		AlphaBlendEnable	= TRUE;
		AlphaRef			= 100;
		AlphaTestEnable		= FALSE;		
		AlphaFunc			= GREATER;

		ZEnable				= TRUE;
		ZWriteEnable		= FALSE;
		ZFunc				= LESSEQUAL;

		SrcBlend			= SRCALPHA;
		DestBlend			= INVSRCALPHA;  

		VertexShader = compile vs_2_0 VShaderInstanced();
		PixelShader  = compile ps_2_0 PShader();
    }

	pass Pass1
    {    
		FillMode	= SOLID;

		Lighting	= FALSE;
		Clipping	= FALSE;
		CullMode	= NONE;

		FogEnable	= FALSE;
		FogColor	= 0x00000000;
		FogDensity	= 1.0f;
		FogEnd		= 10000.0f;
		FogStart	= 50.0f;

		AlphaBlendEnable	= FALSE;
		AlphaRef			= 200;
		AlphaTestEnable		= TRUE;		
		AlphaFunc			= GREATEREQUAL;	

		ZEnable				= TRUE;
		ZWriteEnable		= TRUE;
		ZFunc				= LESSEQUAL;

		SrcBlend			= SRCALPHA;
		DestBlend			= INVSRCALPHA;  

		VertexShader = compile vs_2_0 VShaderInstanced();
		PixelShader  = compile ps_2_0 PShader();
    }   
}
