//
// Bump + Diffuse + Specular (animated bump)
//-uses two fixed light sources, specular contribution reduced by half on each light

/************* UNTWEAKABLES **************/

float4x4 WorldIT : WorldInverseTranspose;
float4x4 WorldViewProj : WorldViewProjection;
float4x4 World : World;
float4x4 ViewInv : ViewInverse;

/*********** DBPRO UNTWEAKABLES **********/
float4x4 boneMatrix[32] : BoneMatrixPalette;


/******SKY COLORS*******************/

float4 groundColor
<
	string UIName = "Color";
	string UIWidget = "Color";
> = {0.5f, 0.5f, 0.5f, 1.0f };

float4 skyColor
<
	string UIName = "Color";
	string UIWidget = "Color";
> = {0.9f, 0.9f, 1.0f, 1.0f };



/************* SURFACE **************/

float4 LightPos : Position
<
    string UIObject = "PointLight";
    string Space = "World";
> = { -100.000000, 700.000000, -200.000000, 1.000000 };


float4 FixedLightSource
<
    string UIType = "Fixed Light Source";
> = {200.0f,300.0f, 300.0f, 1.0f};

float4 FixedLightSource2
<
    string UIType = "Fixed Light Source";
> = {-200.0f, 300.0f, -1000.0f, 1.0f};

//not used in this shader
float4 LightColor
<
	string UIType = "Color";
> = {0.75f, 0.75f, 0.75f, 1.0f};

//this value is pulled from FPSC - non tweakable
float4 AmbiColor : Ambient
<
    string UIName =  "Ambient Light Color";
> = {0.01f, 0.01f, 0.01f, 1.0f};

//this value is also pulled from fpsc - used with Ambicolor to calculate light decay
float4 SurfColor : Diffuse
<
    string UIName =  "Surface Color";
    string UIType = "Color";
> = {1.0f, 1.0f, 1.0f, 1.0f};

float SpecExpon : Power
<
    string UIWidget = "slider";
    float UIMin = 1.0;
    float UIMax = 128.0;
    float UIStep = 1.0;
    string UIName =  "specular power";
> = 40.0;




float Alphavalue : AlphaOverride
<
    string UIName =  "Alpha Override";
> = 1.0f;

/************* TEXTURES **************/

texture colorTexture : DiffuseMap
<
    string Name = "default_color.dds";
    string type = "2D";
>;

texture normalTexture : DiffuseMap
<
    string Name = "default_bump_normal.dds";
    string type = "2D";
>;

texture reflectMap : ReflectMap
<
	string Name = "default_mask.dds";
    string type = "2D";
>;

sampler2D colorSampler = sampler_state
{
	Texture = <colorTexture>;
	MinFilter = Linear;
	MagFilter = Linear;
	MipFilter = Linear;
};

sampler2D normalSampler = sampler_state
{
	Texture = <normalTexture>;
	MinFilter = Linear;
	MagFilter = Linear;
	MipFilter = Linear;
};

sampler2D reflectSampler = sampler_state
{
	Texture = <reflectMap>;
	MinFilter = Linear;
	MagFilter = Linear;
	MipFilter = Linear;
};

/************* DATA STRUCTS **************/

struct appdata {
    float3 Position	: POSITION;
    float4 UV		: TEXCOORD0;
    float4 Normal	: NORMAL;
    float4 Tangent	: TANGENT0;
    float4 Binormal	: BINORMAL0;
    float4 Blendweight	: TEXCOORD1;
    float4 Blendindices	: TEXCOORD2;
};

/* data passed from vertex shader to pixel shader */
struct vertexOutput {
    float4 HPosition	: POSITION;
    float4 TexCoord	: TEXCOORD0;
    float3 LightVec	: TEXCOORD1;
    float3 WorldNormal	: TEXCOORD2;
    float3 WorldEyeVec	: TEXCOORD3;
    float3 WorldTangent	: TEXCOORD4;
    float3 WorldBinorm	: TEXCOORD5;
    float3 LightVec2	: TEXCOORD6;
};

/*********** vertex shader ******/

vertexOutput mainVS(appdata IN)
{
    vertexOutput OUT;
    float3 netPosition = 0, netNormal = 0;
    for (int i = 0; i < 4; i++)
    {
     float index = IN.Blendindices[i];
     float3x4 model = float3x4(boneMatrix[index][0], boneMatrix[index][1], boneMatrix[index][2]);
     float3 vec3 = mul(model, float4(IN.Position, 1));
     vec3 = vec3 + boneMatrix[index][3].xyz;
     float3x3 rotate = float3x3(model[0].xyz, model[1].xyz, model[2].xyz); 
     float3 norm3 = mul(rotate, IN.Normal);
     netPosition += vec3.xyz * IN.Blendweight[i];
     netNormal += norm3.xyz * IN.Blendweight[i];
    }
    float4 tempPos = float4(netPosition,1.0);
    netNormal = normalize(netNormal);

    float3 worldSpacePos = mul(tempPos, World).xyz;
    OUT.WorldNormal = mul(netNormal, WorldIT).xyz;
    OUT.WorldTangent = mul(IN.Tangent, WorldIT).xyz;
    OUT.WorldBinorm = mul(IN.Binormal, WorldIT).xyz;
    OUT.LightVec = FixedLightSource - worldSpacePos;
    OUT.LightVec2 = FixedLightSource2 - worldSpacePos;
    OUT.TexCoord = IN.UV;
    OUT.WorldEyeVec = normalize(ViewInv[3].xyz - worldSpacePos);
    OUT.HPosition = mul(tempPos, WorldViewProj);
    return OUT;
}

/********* pixel shader ********/

float4 mainPS(vertexOutput IN) : COLOR
{
    float4 diffusemap = tex2D(colorSampler,IN.TexCoord.xy);
    float4 specmap = tex2D(reflectSampler,IN.TexCoord.xy);

    float3 normalmap = tex2D(normalSampler,IN.TexCoord.xy) * 2 - 1;
    float3 Ln = normalize(IN.LightVec);
    float3 Ln2 = normalize(IN.LightVec2);
    float3 Nn = normalize(IN.WorldNormal);
    float3 Tn = normalize(IN.WorldTangent);
    float3 Bn = normalize(IN.WorldBinorm);
    float3 Nb = (normalmap.z * Nn) + (1.0*(normalmap.x * Tn + normalmap.y * Bn));
    Nb = normalize(Nb);
    float3 Vn = normalize(IN.WorldEyeVec);
    float3 Hn = normalize(Vn + Ln);
    float3 Hn2 = normalize(Vn + Ln2);
    float4 lighting = lit(dot(Ln,Nb),dot(Hn,Nb),SpecExpon);
    float4 lighting2 = lit(dot(Ln2,Nb),dot(Hn2,Nb),SpecExpon);
    float hdn = lighting.z;
    float ldn = lighting.y;

//calculate whether the per-pixel normal is facing up or down, and use to blend between sky and ground colors
    //this will be added to the ambient color
    float4 sky = lerp(groundColor, skyColor, Nb.g); 

    
    float4 diffContrib2 = SurfColor * diffusemap * (ldn) ;
    float4 diffContrib3 = SurfColor * diffusemap * (lighting2.y) ;
    
    float4 diffContrib = diffContrib3 + diffContrib2 ;
    float4 ambContrib =  ((AmbiColor+0.1) * sky * diffusemap);	
    float4 specContrib = (0.9*SurfColor) *  specmap * hdn;
    float4 specContrib2 = (0.9*SurfColor) *  specmap* lighting2.z;

    //float4 selfIll = specmap.w * diffusemap;

    float4 result = diffContrib + 0.5*specContrib + 0.5*specContrib2 +ambContrib ;
    result.a=diffusemap.a * Alphavalue;

    return result;
}


/****** technique *******/

technique dx9textured
{
	pass p0 
	{		
	        // lighting
        	Lighting       = FALSE;
        	SpecularEnable = FALSE;
	        FogEnable      = FALSE;

		// same vertex shader for both DX9 techniques
		VertexShader = compile vs_2_0 mainVS();
		ZEnable = true;
		ZWriteEnable = true;
		CullMode = None;
		PixelShader = compile ps_3_0 mainPS();
	}
}

/***************************** eof ***/
