/* COMPATIBILITY 
   - HLSL compilers
   - Cg   compilers
*/

/*
 * (Inaccurate) Phosphor shader
 * Author: Themaister
 * Licesese: Public Domain
 */

// Constants used with gamma correction.
#define InputGamma 2.4
#define OutputGamma 2.2

#define GAMMA_IN(color)     pow(color, float3(InputGamma, InputGamma, InputGamma))
#define GAMMA_OUT(color)    pow(color, float3(1.0 / OutputGamma, 1.0 / OutputGamma, 1.0 / OutputGamma))

#define TEX2D(coords)	GAMMA_IN( tex2D(samp, coords).rgb )

// Used to counteract the desaturation effect of weighting.
#define COLOR_BOOST 1.45

struct coords
{
   float2 coord;
   float2 coord_prev;
   float2 coord_prev_prev;
   float2 tex_index;
};

struct input
{
   float2 video_size;
   float2 texture_size;
   float2 output_size;
   float  frame_count;
   float  frame_direction;
   float frame_rotation;
};

void main_vertex(
   float4 position : POSITION,
   out float4 oPosition : POSITION,
   uniform float4x4 modelViewProj,

   float2 tex : TEXCOORD,

   uniform input IN,
   out coords co : TEXCOORD1
)
{
   oPosition = mul(modelViewProj, position);

   float2 one_x = float2(1.0 / (3.0 * IN.texture_size.x), 0.0);
   co.coord = tex - 0.0 * one_x;
   co.coord_prev = tex - 1.0 * one_x;
   co.coord_prev_prev = tex - 2.0 * one_x;
   co.tex_index = tex * IN.texture_size;
}

float3 to_focus(float pixel)
{
   pixel = fmod(pixel + 3.0, 3.0);
   if (pixel >= 2.0) // Blue
      return float3(pixel - 2.0, 0.0, 3.0 - pixel);
   else if (pixel >= 1.0) // Green
      return float3(0.0, 2.0 - pixel, pixel - 1.0);
   else // Red
      return float3(1.0 - pixel, pixel, 0.0);
}

float4 main_fragment(in coords co : TEXCOORD1, uniform sampler2D samp : TEXUNIT0) : COLOR
{
   float y = fmod(co.tex_index.y, 1.0);
   float intensity = exp(-0.2 * y);

   float3 color = TEX2D(co.coord);
   float3 color_prev = TEX2D(co.coord_prev);
   float3 color_prev_prev = TEX2D(co.coord_prev_prev);

   float pixel_x = 3.0 * co.tex_index.x;

   float3 focus = to_focus(pixel_x - 0.0);
   float3 focus_prev = to_focus(pixel_x - 1.0);
   float3 focus_prev_prev = to_focus(pixel_x - 2.0);

   float3 result =
      0.8 * color * focus +
      0.6 * color_prev * focus_prev +
      0.3 * color_prev_prev * focus_prev_prev;

   result = 2.3 * pow(result, float3(1.4, 1.4, 1.4));

   result *= float3( COLOR_BOOST, COLOR_BOOST, COLOR_BOOST );

   return float4(clamp( GAMMA_OUT(intensity * result), 0.0, 1.0 ), 1.0);
}
