struct data
{
   float2 pix_no;
   float one;
};

struct input
{
   float2 video_size;
   float2 texture_size;
   float2 output_size;
};

void main_vertex
(
   float4 position : POSITION,
   out float4 oPosition : POSITION,
   uniform float4x4 modelViewProj,
   float2 tex : TEXCOORD,
   uniform input IN,
   out data oData
)
{
   oPosition = mul(modelViewProj, position);
   oData.pix_no = tex * IN.texture_size - float2(0.0, 0.5);
   oData.one = 1.0 / IN.texture_size.y;
}

#define CRT_GEOM_BEAM 1

float3 beam(float3 color, float dist)
{
#if CRT_GEOM_BEAM
   float3 wid = 2.0 + 2.0 * pow(color, 4.0);
   float3 weights = float3(abs(dist) / 0.3);
   return 2.0 * color * exp(-pow(weights * rsqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
#else
   const float width = 0.25;
   float3 x = dist / width;
   return 2.0 * color * exp(-0.5 * x * x) / width;
#endif
}

#pragma parameter BOOST "Color Boost" 1.0 0.5 1.5 0.02
#ifdef PARAMETER_UNIFORM
uniform float BOOST;
#else
#define BOOST 1.0
#endif

float4 main_fragment (uniform input IN, in data vertex, uniform sampler2D s0 : TEXUNIT0) : COLOR
{
#define TEX(off_y) tex2D(s0, tex + float2(0.0, off_y * vertex.one)).rgb

   float2 texel = floor(vertex.pix_no);
   float phase = vertex.pix_no.y - texel.y;
   float2 tex = float2(texel + 0.5) / IN.texture_size;

   float3 top = TEX(0);
   float3 bottom = TEX(1);

   float dist0 = phase;
   float dist1 = 1.0 - phase;

   float3 scanline = float3(0.0);

   scanline += beam(top, dist0);
   scanline += beam(bottom, dist1);

   return float4(BOOST * scanline / 1.15, 1.0);
}

