/* Start File Header -------------------------------------------------------
Copyright (C) 2010 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited.
File Name: transform.fx
Purpose: The shader for handling the drawing of 3D animating, and not animation models
Authors: Robert Francis - 100%
- End File Header --------------------------------------------------------*/

texture texture0;
texture normalMap;
texture vine;
texture vine2;
float4x4 worldViewProj : WorldViewProjection;
float4x4 world : World;
float3 lightPos = float3(0,1000,0);
static const int MaxMatrices = 80;
float4x3   WorldMatrixArray[MaxMatrices] : WORLDMATRIXARRAY;
float4 vine1Start, vine2Start;
float vine1Dist1, vine2Dist1;
float vine1Dist2, vine2Dist2;
float noLighting = 0.0f;

sampler NormalSamp
{
    Texture   = normalMap;
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    AddressU = WRAP;
    AddressV = WRAP;
    AddressW = WRAP;            
};

sampler Sampler
{
    Texture   = texture0;
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    AddressU = WRAP;
    AddressV = WRAP;
    AddressW = WRAP;            
};

sampler VineSampler
{
    Texture   = vine;
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    AddressU = WRAP;
    AddressV = WRAP;
    AddressW = WRAP;            
};

sampler Vine2Sampler
{
    Texture   = vine2;
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    AddressU = WRAP;
    AddressV = WRAP;
    AddressW = WRAP;            
};

struct VS_INPUT
{
	// stream 0
	float3 position	: POSITION;
	float3 normal : NORMAL;
	float2 tex0 : TEXCOORD0;
	float3 tangent : TANGENT;
	float3 binormal : BINORMAL;
	
	// stream 1
	// World Matrix
	float4 matrix0 : TEXCOORD1;
	float4 matrix1 : TEXCOORD2;
    float4 matrix2 : TEXCOORD3;
    float4 matrix3 : TEXCOORD4;
    
    float4 color : TEXCOORD5;
};

struct VS_INPUT_SKIN
{
	// stream 0
    float4 position	: POSITION;
    float3 normal : NORMAL;
	float2 tex0 : TEXCOORD0;
	float3 tangent : TANGENT;
	float3 binormal : BINORMAL;
    float4 BlendWeights : BLENDWEIGHT;
    float4 BlendIndices : BLENDINDICES;
    
	// stream 1
	// world matrix
	float4 matrix0 : TEXCOORD1;
	float4 matrix1 : TEXCOORD2;
    float4 matrix2 : TEXCOORD3;
    float4 matrix3 : TEXCOORD4;
    
    float4 color : TEXCOORD5;
};


struct VS_OUTPUT
{
    float4 pos : POSITION;
	float2 tex0  : TEXCOORD0;
    float3 normal : TEXCOORD1;
    float3 tangent : TEXCOORD2;
	float3 binormal : TEXCOORD3;
	float4 oldPos : TEXCOORD4;
	float3 oldNorm : TEXCOORD5;
	float4 color : TEXCOORD6;
};

VS_OUTPUT SimpleVertex( VS_INPUT IN )
{
    VS_OUTPUT OUT;
    float4x4 modelMatrix = {IN.matrix0, IN.matrix1, IN.matrix2, IN.matrix3};
    OUT.pos = mul( float4(IN.position, 1) , modelMatrix);
    OUT.oldPos = OUT.pos;
	OUT.pos = mul( OUT.pos , worldViewProj);
	
	float4 temp = mul( float4(IN.normal, 0) , modelMatrix ); 
	OUT.oldNorm = temp.xyz;
	temp = mul( temp, world );
	OUT.normal = float3(temp.x, temp.y, temp.z);
	
	temp = mul( float4(IN.tangent, 0) , modelMatrix );
	temp = mul( temp , world );
	OUT.tangent = float3(temp.x, temp.y, temp.z);
	
	temp = mul( float4(IN.binormal, 0) , modelMatrix );
	temp = mul( temp , world );
	OUT.binormal = float3(temp.x, temp.y, temp.z);
	
	OUT.tex0 = IN.tex0;
	OUT.color = IN.color;
	return OUT;
}

struct PS_OUT
{
  float4 color0: COLOR0;
  float4 color1: COLOR1;
};

PS_OUT SimplePixel( VS_OUTPUT IN ) : COLOR
{
	float4 texColor = tex2D( Sampler , IN.tex0 );
	if(texColor.w < 0.1f)
	  clip(-1);
	texColor *= IN.color;
	PS_OUT OUT;
	OUT.color0 = texColor;
	OUT.color1 = float4(noLighting, 0, 0, 255);
	return OUT;
}

PS_OUT VinePixel( VS_OUTPUT IN ) : COLOR
{
	float4 texColor = tex2D( Sampler , IN.tex0 );
	texColor *= IN.color;
	float4 vec1 = IN.oldPos - vine1Start;
	float4 vec2 = IN.oldPos - vine2Start;
	float dist1 = length(vec1);
	float dist2 = length(vec2);
	float vine11 = step(dist1, vine1Dist1);
	float vine12 = step(dist1, vine1Dist2);
	float vine21 = step(dist2, vine2Dist1);
	float vine22 = step(dist2, vine2Dist2);
	float4 UV1, UV2;
	float x = abs(IN.oldNorm.x);
	float y = abs(IN.oldNorm.y);
	float z = abs(IN.oldNorm.z);
	
	if(x >= y && x >= z)
	{
		UV1.xy = vec1.yz;
		UV2.xy = vec2.yz;
	}
	else if(y >= x && y >= z)
	{
		UV1.xy = vec1.xz;
		UV2.xy = vec2.xz;
	}
	else // z is max
	{
		UV1.xy = vec1.xy;
		UV2.xy = vec2.xy;
	}
	
	UV1.zw = UV1.xy;
	UV2.zw = UV2.xy;
	UV1.xy /= vine1Dist1;
	UV1.zw /= vine1Dist2;
	UV2.xy /= vine2Dist1;
	UV2.zw /= vine2Dist2;
	
	UV1.x = UV1.x * 0.5 + 0.5;
	UV1.y = -UV1.y * 0.5 + 0.5;
	UV1.z = UV1.z * 0.5 + 0.5;
	UV1.w = -UV1.w * 0.5 + 0.5;
	UV2.x = UV2.x * 0.5 + 0.5;
	UV2.y = -UV2.y * 0.5 + 0.5;
	UV2.z = UV2.z * 0.5 + 0.5;
	UV2.w = -UV2.w * 0.5 + 0.5;
	
	float4 vine1Color1 = tex2D( VineSampler, UV1.xy);
	float4 vine1Color2 = tex2D( Vine2Sampler, UV1.zw) * vine12;
	
	float4 vine2Color1 = tex2D( VineSampler, UV2.xy);
	float4 vine2Color2 = tex2D( Vine2Sampler, UV2.zw) * vine22;
	
	vine12 *= !vine1Color1.w;
	vine1Color1 *= vine11;
	
	vine22 *= !vine2Color1.w;
	vine2Color1 *= vine21;
	
	texColor = float4(texColor.xyz + vine1Color1.xyz * vine1Color1.w + 
	vine1Color2.xyz * vine1Color2.w + 
	vine2Color1.xyz * vine2Color1.w + 
	vine2Color2.xyz * vine2Color2.w, texColor.w);
	
  PS_OUT OUT;
	OUT.color0 = texColor;
	OUT.color1 = float4(noLighting, 0, 0, 255);
	return OUT;
}

VS_OUTPUT SkinVertex( VS_INPUT_SKIN IN , uniform int NumBones )
{
    VS_OUTPUT OUT;
    
    float3 Pos = float3(0,0,0);
    float3 Normal = float3(0,0,0);	
    float3 Tangent = float3(0,0,0);
    float3 Binormal = float3(0,0,0);
   
    float BlendWeightsArray[4] = (float[4])IN.BlendWeights;
    int   IndexArray[4]        = (int[4])IN.BlendIndices;
	    
	for (int iBone = 0; iBone < NumBones ; iBone++)
    {       
        Pos += mul( IN.position , WorldMatrixArray[IndexArray[iBone]]) * BlendWeightsArray[iBone];
        Normal += (float3)mul(float4(IN.normal,0) , WorldMatrixArray[IndexArray[iBone]]) * BlendWeightsArray[iBone];
        Tangent += (float3)mul(float4(IN.tangent,0) , WorldMatrixArray[IndexArray[iBone]]) * BlendWeightsArray[iBone];
        Binormal += (float3)mul(float4(IN.binormal,0) , WorldMatrixArray[IndexArray[iBone]]) * BlendWeightsArray[iBone];
    }
        
	Normal = normalize(Normal);
	Tangent = normalize(Tangent);
	Binormal = normalize(Binormal);
	float4x4 modelMatrix =  {IN.matrix0, IN.matrix1, IN.matrix2, IN.matrix3};
	
	OUT.pos = mul( float4( Pos, 1) , modelMatrix);
	OUT.oldPos = OUT.pos;
	OUT.pos = mul( OUT.pos, worldViewProj);
	
	OUT.normal = (float3)mul( float4(Normal, 0) , modelMatrix );
	OUT.oldNorm = OUT.normal;
	OUT.normal = (float3)mul( float4(OUT.normal, 0) , world );	
	
	OUT.tangent = (float3)mul( float4(Tangent, 0) , modelMatrix );
	OUT.tangent = (float3)mul( float4(OUT.tangent, 0) , world );	
	
	OUT.binormal = (float3)mul( float4(Binormal, 0) , modelMatrix );
	OUT.binormal = (float3)mul( float4(OUT.binormal, 0) , world );	
	
	OUT.tex0 = IN.tex0;
	OUT.color = IN.color;
	return OUT;
}

technique Technique0
{
    pass Pass0
    {
        VertexShader = compile vs_2_0 SimpleVertex();
        PixelShader  = compile ps_2_0 SimplePixel();
        ZEnable = true;
        AlphaBlendEnable = false;
        SrcBlend = SrcAlpha;
        DestBlend = InvSrcAlpha;
        SrcBlendAlpha = ONE;
        DestBlendAlpha = ONE;
    }
}

technique TechniqueVine
{
    pass Pass0
    {
        VertexShader = compile vs_2_0 SimpleVertex();
        PixelShader  = compile ps_2_0 VinePixel();
        ZEnable = true;
        AlphaBlendEnable = true;
        SrcBlend = SrcAlpha;
        DestBlend = InvSrcAlpha;
        SrcBlendAlpha = ONE;
        DestBlendAlpha = ONE;
    }
}

technique TechniqueSkin
{
    pass Pass0
    {
        VertexShader = compile vs_2_0 SkinVertex( 4 );
        PixelShader  = compile ps_2_0 SimplePixel();
        ZEnable = true;
        AlphaBlendEnable = false;
        SrcBlend = SrcAlpha;
        DestBlend = InvSrcAlpha;
        SrcBlendAlpha = ONE;
        DestBlendAlpha = ONE;
    }
}