texture Texture;
texture Texture2;
float fTime;			  // Time parameter. This keeps increasing
float4 LineColor = float4(1.0f, 0.7f, 0.7f, 0.5f);

uniform float ShaderData[128] : register(c1);
uniform float ShaderTimer;

struct PS_INPUT
{
	float4 Position   : POSITION;   // vertex position 
	float4 Color     : COLOR0;
	float2 Texture   : TEXCOORD0;
	float3 Normal    : TEXCOORD1;
	float4 Data      : TEXCOORD2;
	float4 Data2     : TEXCOORD3;
};

struct PS_OUTPUT
{
    float4 Color    : COLOR0;     // vertex diffuse color
};

sampler2D textureSampler = sampler_state 
{
    Texture = (Texture);
    MinFilter = Linear;
	MipFilter = Linear;
    MagFilter = Linear;
    AddressU = Wrap;
    AddressV = Wrap;
};

sampler2D texture2Sampler = sampler_state 
{
    Texture = (Texture2);
    MinFilter = Linear;
	MipFilter = Linear;
    MagFilter = Linear;
    AddressU = Wrap;
    AddressV = Wrap;
};

PS_OUTPUT OutlineColor( in PS_INPUT p)
{
	PS_OUTPUT Output;
	Output.Color = tex2D( textureSampler, p.Texture );
	Output.Color = Output.Color * p.Color;
	Output.Color.a *= LineColor.a;
	Output.Color.r *= LineColor.r;
	Output.Color.g *= LineColor.g;
	Output.Color.b *= LineColor.b;

	//Output.Color = Output.Color * p.Color;
    return Output;
}

PS_OUTPUT CelColor( in PS_INPUT p)
{
	float3 LightDir = float3(0.5f,0.7f,0.5f);
	PS_OUTPUT Output = (PS_OUTPUT)0;
	float4 diffuse = tex2D(textureSampler, p.Texture);
	float normal = saturate(dot(LightDir, p.Normal));
	
	Output.Color = float4(0.8,0.8,0.8,1.0f) * diffuse;
	float total = normal;
	if(total < 0.1)
		Output.Color += float4(0.1,0.1,0.1,1.0f) * diffuse;
	else if(total < 0.3)
		Output.Color += float4(total,total,total,1.0f) * diffuse;
	else
		Output.Color += float4(0.3,0.3,0.3,1.0f) * diffuse;
	
	Output.Color.a = Output.Color.a * LineColor.a;
	Output.Color.r = Output.Color.r * LineColor.r;
	Output.Color.g = Output.Color.g * LineColor.g;
	Output.Color.b = Output.Color.b * LineColor.b;
		
    return Output;
}

PS_OUTPUT LightColor( in PS_INPUT p)
{
	PS_OUTPUT Output = (PS_OUTPUT)0;
	float4 diffuse = tex2D(textureSampler, p.Texture);
	
	Output.Color = diffuse * 0.5f;
	Output.Color.a = 1.0f;
	
	float4 original = p.Data2;
	float weight = 0.0f;
	float light = 0.0f;

	int loopTimes = 8;
	for(int l=0;l < loopTimes;l++)
	{
		int dataPos = l * 8;
		float range = ShaderData[dataPos];
		if(range > 0)
		{
			float3 center = float3(ShaderData[dataPos + 1],ShaderData[dataPos + 2],ShaderData[dataPos + 3]);
			float3 color  = float3(ShaderData[dataPos + 4],ShaderData[dataPos + 5],ShaderData[dataPos + 6]);
			float3 dis = float3(original.x - center.x,original.y - center.y,original.z - center.z);
			float distance = sqrt(dis.x * dis.x + dis.z * dis.z);
			weight = (range * 2 - distance) / range;

			if(weight <= 0.5f)
			{
			}
			else if(weight < 1.0f)
			{
				Output.Color.rgb += diffuse.rgb * color * (0.3f + weight - 0.5f);
			}
			else
				Output.Color.rgb += diffuse.rgb * color  * 0.8f;
		}
	}

	Output.Color.a = Output.Color.a * LineColor.a;
	Output.Color.r = Output.Color.r * LineColor.r;
	Output.Color.g = Output.Color.g * LineColor.g;
	Output.Color.b = Output.Color.b * LineColor.b;
	
	return Output;
}

PS_OUTPUT Grayscale( in PS_INPUT p)
{
	PS_OUTPUT Output = (PS_OUTPUT)0;
	float4 diffuse = tex2D(textureSampler, p.Texture);
	float3 table = float3(0.3f,0.59f,0.11f);
	
	//float4 gray = dot(diffuse.rgb, table);
	float gray = diffuse.r * table.r + diffuse.g * table.g + diffuse.b * table.b;
	
	//float4 newGray = gray;
	Output.Color.r = gray;
	Output.Color.g = gray;
	Output.Color.b = gray;
	Output.Color.a = 1.0f;

	//clip(Output.Color.r < 0.9f ? -1:1);
	
    return Output;
}

PS_OUTPUT Mosaic( in PS_INPUT p)
{
	PS_OUTPUT Output = (PS_OUTPUT)0;
	float2 tex = p.Texture;
	if(tex.x >= 0.4f && tex.x < 0.7f &&
	   tex.y >= 0.4f && tex.y < 0.7f)
	{
		tex.x = (float)((int)(tex.x * 2000.0f) / 10) / 200.0f;
		tex.y = (float)((int)(tex.y * 2000.0f) / 10) / 200.0f;
	}
	
	float4 diffuse = tex2D(textureSampler, tex);
	Output.Color = diffuse;
	Output.Color.a = 1.0f;
	
    return Output;
}

PS_OUTPUT Bloom( in PS_INPUT p)
{
	PS_OUTPUT Output;
	
	Output.Color = tex2D(texture2Sampler, p.Texture);
	if(Output.Color.b > Output.Color.r && Output.Color.b > Output.Color.g)
	{
		//Output.Color = p.Color;
		float temp = Output.Color.r;
		Output.Color.r = Output.Color.b * 2;
		Output.Color.b = temp;
	}
	//Output.Color = p.Color;
		
    return Output;
}

PS_OUTPUT Concentrate( in PS_INPUT p)
{
	PS_OUTPUT Output = (PS_OUTPUT)0;
	float2 tex = p.Texture;
	float2 cDis = p.Texture - float2(0.5f,0.5f);
	float r = 180.0f + (atan2(cDis.y,cDis.x) / 3.1415f) * 180.0f;
	float range = fTime / 90.0f;
	float pointDis = sqrt(cDis.x * cDis.x + cDis.y * cDis.y);
	if(pointDis < range)
	{
	}	
	else
	{
		float minR = range;
		float2 minP;
		
		minP.x = -minR * cos(radians(r));
		minP.y = -minR * sin(radians(r));

		float newX = minP.x;
		float newY = minP.y;
		//float newX = -pointDis * cos(radians(r));
		//float newY = -pointDis * sin(radians(r));
		tex.x = 0.5f + (newX + cDis.x / 10.0f);
		tex.y = 0.5f + (newY + cDis.y / 10.0f);
	}
	
	float4 diffuse = tex2D(textureSampler, tex);;
	
	Output.Color = diffuse;
	Output.Color.a = 1.0f;
	
    return Output;
}

PS_OUTPUT Shield( in PS_INPUT p)
{
	PS_OUTPUT Output = (PS_OUTPUT)0;
	float3 LightDir = float3(0.0f,0.0f,-1.2f);
	float normal = saturate(dot(LightDir, p.Normal));

	Output.Color.rgb = LineColor.rgb;
	Output.Color.a = (1.0f - normal) * 0.5f;
	
    return Output;
}

PS_OUTPUT SnowColor( in PS_INPUT p)
{
	PS_OUTPUT Output = (PS_OUTPUT)0;
	float4 diffuse = tex2D(textureSampler, p.Texture) * p.Color;
	
	Output.Color.a = diffuse.a;
	
	float4 original = p.Data2;
	float weight = 0.0f;
	float light = 0.0f;

	float depth = min(ShaderTimer / 60.0f,1.0f);

	float3 sColor = float3(0.0f,0.0f,0.0f);
	float  lightRate = 0.0f;
	int loopTimes = 16;
	for(int l=0;l < loopTimes;l++)
	{
		int dataPos = l * 8;
		float range = ShaderData[dataPos];
		if(range > 0)
		{
			float3 center = float3(ShaderData[dataPos + 1],ShaderData[dataPos + 2],ShaderData[dataPos + 3]);
			float3 color  = float3(ShaderData[dataPos + 4],ShaderData[dataPos + 5],ShaderData[dataPos + 6]);
			float3 dis = float3(original.x - center.x,original.y - center.y,original.z - center.z);
			float distance = sqrt(dis.x * dis.x + dis.z * dis.z);
			weight = (range * 2 - distance) / range;

			if(weight <= 0.5f)
			{
			}
			else if(weight < 1.0f)
			{
				lightRate += (0.1f + weight - 0.5f);
			}
			else
			{
				lightRate += 0.6f;
			}
		}
	}

	if(lightRate <= 0.0f)
		sColor = float3(0.5f,0.5f,0.5f) + diffuse.rgb * 0.01f;
	else if(lightRate < 1.0f)
		sColor = float3(0.5f,0.5f,0.5f) * (1.0f - lightRate) + diffuse.rgb * lightRate;
	else
		sColor = diffuse.rgb * lightRate;

	Output.Color.rgb = sColor * depth + diffuse * (1.0f - depth);

	Output.Color.a = Output.Color.a * LineColor.a;
	Output.Color.r = Output.Color.r * LineColor.r;
	Output.Color.g = Output.Color.g * LineColor.g;
	Output.Color.b = Output.Color.b * LineColor.b;

	return Output;
}

PS_OUTPUT BallColor( in PS_INPUT p)
{
	PS_OUTPUT Output = (PS_OUTPUT)0;
	float4 diffuse = tex2D(textureSampler, p.Texture);
	float3 LightDir = float3(0.0f,0.0f,-1.2f);
	int dataPos = 0;
	float range = ShaderData[dataPos];
	float4 original = p.Data2;
	if(range > 0.0f)
	{
		float3 center = float3(ShaderData[dataPos + 1],ShaderData[dataPos + 2],ShaderData[dataPos + 3]);
		float3 dis = float3(original.x - center.x,original.y - center.y,original.z - center.z);
		
		LightDir = dis;
	}

	float normal = saturate(dot(LightDir, p.Normal));

	Output.Color.r = 0.3f + (normal) * 0.2f;
	Output.Color.g = 0.3f + (normal) * 0.1f;
	Output.Color.b = 1.0f + (normal) * 0.2f;
	Output.Color.a = 0.3f;

	Output.Color.rgb = Output.Color.rgb * 0.7f + diffuse.rgb * 0.3f;

	return Output;
}