// Halftone.fx
//
// Based on
// VVVV Halftone.fx by sanch and gregsn

float4x4 tW: WORLD;        //the models world matrix
float4x4 tV: VIEW;         //view matrix as set via Renderer (DX9)
float4x4 tP: PROJECTION;   //projection matrix as set via Renderer (DX9)
float4x4 tWVP: WORLDVIEWPROJECTION;
  
float V_Alpha  : ALPHA;
float NumTiles : VAR1; // = 50 (1->100)
float Sat      : VAR2;
float DotSize  = 1;
float Softness = 0.1;

//////////////////////// vertex shader //////////////////////////////
struct vertexOutput
{
  float4 HPosition  : POSITION;
  float4 UV         : TEXCOORD0;
  float  stride     : TEXCOORD1;
  float  dotsize    : TEXCOORD2;
  float  halfstride : TEXCOORD3;
};

vertexOutput VS_Quad(float4 Position: POSITION, float4 TexCoord: TEXCOORD0)
{
  vertexOutput OUT = (vertexOutput)0;
  OUT.HPosition    = float4(Position);
  OUT.UV           = TexCoord;
  OUT.stride       = 1.0/(NumTiles*90+10);
  OUT.halfstride   = OUT.stride*0.5;
  OUT.dotsize      = DotSize * OUT.stride;
  return OUT;
}

//////////////////////// Pixel shader //////////////////////////////
sampler Sampler = sampler_state
{
  MipFilter = LINEAR;
  MinFilter = LINEAR;
  MagFilter = LINEAR;
};

/////////////////// pixel shader /////////////////////////////////////
float4 pixelsPS(vertexOutput IN) : COLOR
{
  float2 PCenter   = IN.UV - fmod(IN.UV, IN.stride) + IN.halfstride;
  //float2 PCenter   = IN.UV - fmod(IN.UV, 1.0/(NumTiles*99+1)) + 1.0/100.0;
  float4 tileColor = tex2D(Sampler,frac(PCenter));
  float4 isinDot   = (length(IN.UV - PCenter) < IN.dotsize / 2) * tileColor;
  //float4 isinDot   = (length(IN.UV - PCenter) < (1.0/50.0 / 2)) * tileColor;
  isinDot.a = V_Alpha;
  return isinDot;
}

///////////////////////////////////////////////////////////////////////
float4 halftonePS(vertexOutput IN) : COLOR {
    float2 Pbase = IN.UV - fmod(IN.UV, IN.stride);
    float2 PCenter = Pbase + IN.halfstride;
    float4 tileColor = tex2D(Sampler,PCenter);

    float bright = length(tileColor.rgb) / 1.732; // white = (1 + 1 + 1)^.5 = 1.732
    float isinDot = length(IN.UV - PCenter) < bright * IN.dotsize;
    float4 result = isinDot;
    result.a = V_Alpha;
    return result;
}

//////////////////////////////////////////////////////////////

float4 softhalftonePS(vertexOutput IN) : COLOR {
    float2 Pbase = IN.UV - fmod(IN.UV, IN.stride);
    float2 PCenter = Pbase + IN.halfstride;
    float4 tileColor = tex2D(Sampler,PCenter);

    float bright = length(tileColor.rgb) / 1.732; // white = (1 + 1 + 1)^.5 = 1.732
    float rad = length(IN.UV - PCenter);
    float s = bright * IN.dotsize;
    float isinDot = rad < s;

    float4 result = .5 - (rad / s - 1) / Softness;
    result = result*(tileColor*Sat);
    result.a = V_Alpha;
    return result;
}

////////////////////////////////////////////////////////////////
float4 overlap5halftoneBWPS(vertexOutput IN) : COLOR
{
  float2 Pbase = IN.UV - fmod(IN.UV, IN.stride);
  float2 PCenter = Pbase + IN.halfstride;

  float2 CurrentCircle = PCenter + float2(0, -1) * IN.stride;
  float4 CurrentColor = tex2D(Sampler,CurrentCircle);
  float bright = CurrentColor.r; //length(CurrentColor.rgb);
  float isinDot = length(IN.UV - CurrentCircle) < bright * IN.dotsize;
  float tileColor = isinDot;

  CurrentCircle = PCenter + float2(0, 1) * IN.stride;
  CurrentColor = tex2D(Sampler,CurrentCircle);
  bright = CurrentColor.r ; //length(CurrentColor.rgb);
  isinDot = length(IN.UV - CurrentCircle) < bright * IN.dotsize;
  tileColor = tileColor + isinDot;

  for (int x = -1; x <= 1; x++)
  {
    CurrentCircle = PCenter + float2(x, 0) * IN.stride;
    CurrentColor = tex2D(Sampler,CurrentCircle);
    bright = CurrentColor.r ; //length(CurrentColor.rgb);
    isinDot = length(IN.UV - CurrentCircle) < bright * IN.dotsize;
    tileColor = tileColor + isinDot;
  }

  float4 result = tileColor*(tileColor*Sat);
  result.a = V_Alpha;
  return result;
}

 
////////////////////////////////////////////////////////////////
float4 linehalftonePS(vertexOutput IN) : COLOR
{
  float2 Pbase = IN.UV - fmod(IN.UV, IN.stride);
  float4 tileColor = tex2D(Sampler,Pbase);
  float bright = tileColor.rgb /1.732; // white = (1 + 1 + 1)^.5 = 1.732
  float isinDot = IN.UV - Pbase < bright * IN.dotsize;
  float4 result = isinDot;
  result.a = V_Alpha;
  return result;
}


///////////////////////////////////////////////////////
float4 halftonepictPS(vertexOutput IN) : COLOR
{
  float2 Pbase     = IN.UV - fmod(IN.UV, IN.stride);
  float4 tile      = tex2D(Sampler,frac(IN.UV*(1.0/IN.stride)));
  float4 tileColor = tex2D(Sampler,frac(Pbase));
  float4 result    = (tile * tileColor) * 2;
  result.a = V_Alpha;
  return result;
}

technique Pixels

{
    pass p0

    {		
		VertexShader = compile vs_2_0 VS_Quad();
	
		PixelShader = compile ps_2_0 pixelsPS();
    }
}

technique Halftone

{
    pass p0

    {		
		VertexShader = compile vs_2_0 VS_Quad();
	
		PixelShader = compile ps_2_0 halftonePS();
    }
}

technique SoftHalftone

{
    pass p0

    {		
		VertexShader = compile vs_2_0 VS_Quad();
	
		PixelShader = compile ps_2_0 softhalftonePS();
    }
}

technique Overlap5HalftoneBW

{
    pass p0

    {		
		VertexShader = compile vs_2_0 VS_Quad();
	
		PixelShader = compile ps_2_0 overlap5halftoneBWPS();
    }
}

 technique LineHalftone

{
    pass p0

    {		
		VertexShader = compile vs_2_0 VS_Quad();
	
		PixelShader = compile ps_2_0 linehalftonePS();
    }
}
technique HalftonePic
{
  pass p0
  {		
  	VertexShader = compile vs_2_0 VS_Quad();
		PixelShader = compile ps_2_0  halftonepictPS();
    }
}

