/*--------------------------------*\
      Gen2 Fireball Shader
\*--------------------------------*/

static const int MAX_BONE_COUNT = 80;
static const int MAX_LIGHT_COUNT = 4;

float3 LightsPointPos[MAX_LIGHT_COUNT];
float2 LightsPointAtt[MAX_LIGHT_COUNT];
float4 LightsPointColor[MAX_LIGHT_COUNT];
float3 LightsDirDir[MAX_LIGHT_COUNT];
float4 LightsDirColor[MAX_LIGHT_COUNT];

uniform int VS_Index;
uniform int PS_Index;

float4x3 g_W;
float4x4 g_WVP;
float4x3 g_SkinPallete[MAX_BONE_COUNT];

texture TexDiffuse0;
texture TexDiffuse1;
texture TexDiffuse2;
texture TexDiffuse3;
texture TexLightMap;

sampler SampDiffuse0 = sampler_state {
    Texture = <TexDiffuse0>;
    MinFilter = Linear;  
    MagFilter = Linear;
    MipFilter = Linear;
    AddressU  = Wrap;
    AddressV  = Wrap;
};

sampler SampDiffuse1 = sampler_state {
    Texture = <TexDiffuse1>;
    MinFilter = Linear;  
    MagFilter = Linear;
    MipFilter = Linear;
    AddressU  = Wrap;
    AddressV  = Wrap;
};

sampler SampDiffuse2 = sampler_state {
    Texture = <TexDiffuse2>;
    MinFilter = Linear;  
    MagFilter = Linear;
    MipFilter = Linear;
    AddressU  = Wrap;
    AddressV  = Wrap;
};

sampler SampDiffuse3 = sampler_state {
    Texture = <TexDiffuse3>;
    MinFilter = Linear;  
    MagFilter = Linear;
    MipFilter = Linear;
    AddressU  = Wrap;
    AddressV  = Wrap;
};

sampler SampLightMap = sampler_state {
    Texture = <TexLightMap>;
    MinFilter = Linear;  
    MagFilter = Linear;
    MipFilter = Linear;
    AddressU  = Clamp;
    AddressV  = Clamp;
};

struct TVS_Input_General_Geom {
	float3 _Position0: Position0;
	float3 _Tangent0: Tangent0;
	float3 _Binormal0: Binormal0;
	float3 _Normal0: Normal0;
	float2 _TexCoord0: TexCoord0;
  float2 _TexCoord1: TexCoord1;
  float4 _Color0: Color0;
};

struct TVS_Output_General_Geom {
  float4 _Position0: Position0;
	float2 _TexCoord0: TexCoord0;
  float2 _TexCoord1: TexCoord1;
  float4 _Color0: Color0;
};

static const float4 AMBIENT_LIGHT = float4(0.2, 0.2, 0.2, 0.2);
float2 g_TexMod = float2(0, 0);

void VS_General_Geom (const in TVS_Input_General_Geom Input, out TVS_Output_General_Geom Output) {
	Output._Position0 = mul(float4(Input._Position0, 1), g_WVP); 
	Output._TexCoord0 = Input._TexCoord0 + g_TexMod;
  Output._TexCoord1 = Input._TexCoord1;
  Output._Color0 = Input._Color0;
}

struct TPS_Input_General_Geom {
	float2 _TexCoord0: TexCoord0;
  float2 _TexCoord1: TexCoord1;
  float4 _Color0: Color0;
};

struct TPS_Output_General_Geom {
	float4 _Color0: Color0;
};

void PS_General_Geom_1 (const in TPS_Input_General_Geom Input, out TPS_Output_General_Geom Output) {
  float4 t0 = tex2D(SampDiffuse0, Input._TexCoord0);
  Output._Color0 = t0 * (tex2D(SampLightMap, Input._TexCoord1) + AMBIENT_LIGHT);
  Output._Color0.w = t0.w;
}

void PS_General_Geom_2 (const in TPS_Input_General_Geom Input, out TPS_Output_General_Geom Output) {
	float4 t0 = tex2D(SampDiffuse0, Input._TexCoord0);
  float4 t1 = tex2D(SampDiffuse1, Input._TexCoord0);
  float4 c = (t0 + (t1 - t0) * Input._Color0.r);
  Output._Color0 = c * (tex2D(SampLightMap, Input._TexCoord1) + AMBIENT_LIGHT);
  Output._Color0.w = c.w;
}

void PS_General_Geom_3 (const in TPS_Input_General_Geom Input, out TPS_Output_General_Geom Output) {
	float4 t0 = tex2D(SampDiffuse0, Input._TexCoord0);
  float4 t1 = tex2D(SampDiffuse1, Input._TexCoord0);
  float4 t2 = tex2D(SampDiffuse2, Input._TexCoord0);
  float4 ct = (t0 + (t1 - t0) * Input._Color0.r);
  float4 c = (ct + (t2 - ct) * Input._Color0.g);
  Output._Color0 = c * (tex2D(SampLightMap, Input._TexCoord1) + AMBIENT_LIGHT);
  Output._Color0.w = c.w;
}

void PS_General_Geom_4 (const in TPS_Input_General_Geom Input, out TPS_Output_General_Geom Output) {
	float4 t0 = tex2D(SampDiffuse0, Input._TexCoord0);
  float4 t1 = tex2D(SampDiffuse1, Input._TexCoord0);
  float4 t2 = tex2D(SampDiffuse2, Input._TexCoord0);
  float4 t3 = tex2D(SampDiffuse3, Input._TexCoord0);
  float4 ct = (t0 + (t1 - t0) * Input._Color0.r);
  ct = (ct + (t2 - ct) * Input._Color0.g);
  float4 c = (ct + (t3 - ct) * Input._Color0.b);
  Output._Color0 = c * (tex2D(SampLightMap, Input._TexCoord1) + AMBIENT_LIGHT);
  Output._Color0.w = c.w;
}

struct TVS_Input_General_Char_0 {
	float3 _Position0: Position0;
	float3 _Tangent0: Tangent0;
	float3 _Binormal0: Binormal0;
	float3 _Normal0: Normal0;
	float2 _TexCoord0: TexCoord0;
};

struct TVS_Input_General_Char_1 {
	float3 _Position0: Position0;
	float3 _Tangent0: Tangent0;
	float3 _Binormal0: Binormal0;
	float3 _Normal0: Normal0;
	float2 _TexCoord0: TexCoord0;
  int _BIndices0: BlendIndices0;
};

struct TVS_Input_General_Char_2 {
	float3 _Position0: Position0;
	float3 _Tangent0: Tangent0;
	float3 _Binormal0: Binormal0;
	float3 _Normal0: Normal0;
	float2 _TexCoord0: TexCoord0;
  int2 _BIndices0: BlendIndices0;
	float2 _BWeights0: BlendWeight0;
};

struct TVS_Input_General_Char_3 {
	float3 _Position0: Position0;
	float3 _Tangent0: Tangent0;
	float3 _Binormal0: Binormal0;
	float3 _Normal0: Normal0;
	float2 _TexCoord0: TexCoord0;
  int3 _BIndices0: BlendIndices0;
	float3 _BWeights0: BlendWeight0;
};

struct TVS_Input_General_Char_4 {
	float3 _Position0: Position0;
	float3 _Tangent0: Tangent0;
	float3 _Binormal0: Binormal0;
	float3 _Normal0: Normal0;
	float2 _TexCoord0: TexCoord0;
  int4 _BIndices0: BlendIndices0;
	float4 _BWeights0: BlendWeight0;
};

struct TVS_Output_General_Char {
	float4 _Position0: Position0;
	float2 _TexCoord: TexCoord0;
	float3 _PositionW: TexCoord1;
	float3 _NormalW: TexCoord2;
};

void VS_General_Char_0 (const in TVS_Input_General_Char_0 Input, out TVS_Output_General_Char Output) {
	Output._Position0 = mul(float4(Input._Position0, 1), g_WVP);
  Output._PositionW = mul(float4(Input._Position0, 1), (float4x3)g_W);
	Output._NormalW = mul(Input._Normal0, (float3x3)g_W);
	Output._TexCoord = Input._TexCoord0;
}

void VS_General_Char_1 (const in TVS_Input_General_Char_1 Input, out TVS_Output_General_Char Output) {
	float4x3 S = g_SkinPallete[Input._BIndices0];
	float4x3 SW = mul(S, g_W);
	float3 PositionS = mul(float4(Input._Position0, 1), S);
	Output._Position0 = mul(float4(PositionS, 1), g_WVP);
  Output._PositionW = mul(float4(PositionS, 1), (float4x3)g_W);
	Output._NormalW = mul(Input._Normal0, (float3x3)SW);
	Output._TexCoord = Input._TexCoord0;
}

void VS_General_Char_2 (const in TVS_Input_General_Char_2 Input, out TVS_Output_General_Char Output) {
	float4x3 S = (
		g_SkinPallete[Input._BIndices0[0]] * Input._BWeights0[0] +
		g_SkinPallete[Input._BIndices0[1]] * Input._BWeights0[1]
	);
	float4x3 SW = mul(S, g_W);
	float3 PositionS = mul(float4(Input._Position0, 1), S);
	Output._Position0 = mul(float4(PositionS, 1), g_WVP);
  Output._PositionW = mul(float4(PositionS, 1), (float4x3)g_W);
	Output._NormalW = mul(Input._Normal0, (float3x3)SW);
	Output._TexCoord = Input._TexCoord0;
}

void VS_General_Char_3 (const in TVS_Input_General_Char_3 Input, out TVS_Output_General_Char Output) {
	float4x3 S = (
		g_SkinPallete[Input._BIndices0[0]] * Input._BWeights0[0] +
		g_SkinPallete[Input._BIndices0[1]] * Input._BWeights0[1] +
		g_SkinPallete[Input._BIndices0[2]] * Input._BWeights0[2]
	);
	float4x3 SW = mul(S, g_W);
	float3 PositionS = mul(float4(Input._Position0, 1), S);
	Output._Position0 = mul(float4(PositionS, 1), g_WVP);
  Output._PositionW = mul(float4(PositionS, 1), (float4x3)g_W);
	Output._NormalW = mul(Input._Normal0, (float3x3)SW);
	Output._TexCoord = Input._TexCoord0;
}

void VS_General_Char_4 (const in TVS_Input_General_Char_4 Input, out TVS_Output_General_Char Output) {
	float4x3 S = (
		g_SkinPallete[Input._BIndices0[0]] * Input._BWeights0[0] +
		g_SkinPallete[Input._BIndices0[1]] * Input._BWeights0[1] +
		g_SkinPallete[Input._BIndices0[2]] * Input._BWeights0[2] +
		g_SkinPallete[Input._BIndices0[3]] * Input._BWeights0[3]
	);
	float4x3 SW = mul(S, g_W);
	float3 PositionS = mul(float4(Input._Position0, 1), S);
	Output._Position0 = mul(float4(PositionS, 1), g_WVP);
  Output._PositionW = mul(float4(PositionS, 1), (float4x3)g_W);
	Output._NormalW = mul(Input._Normal0, (float3x3)SW);
	Output._TexCoord = Input._TexCoord0;
}

struct TPS_Input_General_Char {
	float2 _TexCoord: TexCoord0;
  float3 _PositionW: TexCoord1;
	float3 _NormalW: TexCoord2;
};

struct TPS_Output_General_Char {
	float4 _Color0: Color0;
};

void PS_General_Char (const in TPS_Input_General_Char Input, uniform int LightCountPoint, uniform int LightCountDir, out TPS_Output_General_Char Output) {
  float3 NormalW = normalize(Input._NormalW);
  float4 Color = float4(0, 0, 0, 0);
  for (int i = 0; i < LightCountPoint; i++) {
    float3 LightDirW = (LightsPointPos[i] - Input._PositionW);
    Color += saturate(dot(normalize(LightDirW), NormalW)) * (LightsPointColor[i] * smoothstep(LightsPointAtt[i].y, LightsPointAtt[i].x, length(LightDirW)));
  }
  for (int i = 0; i < LightCountDir; i++) {
    Color += saturate(dot(-LightsDirDir[i], NormalW)) * LightsDirColor[i];
  }
	Output._Color0 = tex2D(SampDiffuse0, Input._TexCoord) * (Color + AMBIENT_LIGHT);
  Output._Color0.w = 1;              
}

VertexShader VS_General_Arr[6] = {
	compile vs_2_0 VS_General_Geom(),
  compile vs_2_0 VS_General_Char_0(),
  compile vs_2_0 VS_General_Char_1(),
  compile vs_2_0 VS_General_Char_2(),
  compile vs_2_0 VS_General_Char_3(),
  compile vs_2_0 VS_General_Char_4()
};

PixelShader PS_General_Arr[19] = {
	compile ps_2_0 PS_General_Geom_1(),
  compile ps_2_0 PS_General_Geom_2(),
  compile ps_2_0 PS_General_Geom_3(),
  compile ps_2_0 PS_General_Geom_4(),
  compile ps_2_0 PS_General_Char(0, 0),
  compile ps_2_0 PS_General_Char(0, 1),
  compile ps_2_0 PS_General_Char(0, 2),
  compile ps_2_0 PS_General_Char(1, 0),
  compile ps_2_0 PS_General_Char(1, 1),
  compile ps_2_0 PS_General_Char(1, 2),
  compile ps_2_0 PS_General_Char(2, 0),
  compile ps_2_0 PS_General_Char(2, 1),
  compile ps_2_0 PS_General_Char(2, 2),
  compile ps_2_0 PS_General_Char(3, 0),
  compile ps_2_0 PS_General_Char(3, 1),
  compile ps_2_0 PS_General_Char(3, 2),
  compile ps_2_0 PS_General_Char(4, 0),
  compile ps_2_0 PS_General_Char(4, 1),
  compile ps_2_0 PS_General_Char(4, 2),
};

technique General {
  pass P0 {
    VertexShader = VS_General_Arr[VS_Index];
    PixelShader = PS_General_Arr[PS_Index];
  }
}