/* COMPATIBILITY
   - HLSL compilers
   - Cg   compilers
 */

#pragma parameter OLDTV_CHROMA "OldTV Chroma"   4.0   0.0 10.0 0.01
#pragma parameter OLDTV_CHROMA_SHIFT "OldTV Chroma Shift" 2048.0 0.0 4096.0 1.00
#pragma parameter OLDTV_BARREL_VALUE "OldTV Barrel Value #1" 0.006 0.0 1.0 0.001
#pragma parameter OLDTV_BARREL_VALUE2 "OldTV Barrel Value #2" 0.5 0.0 1.0 0.01
#pragma parameter OLDTV_USE_BARREL "OldTV Enable Barrel" 0.0 0.0 1.0 1.0
#pragma parameter OLDTV_USE_RAND   "OldTV Enable Rand" 1.0 0.0 1.0 1.0
#pragma parameter OLDTV_USE_LUMA   "OldTV Enable Luma" 0.0 0.0 1.0 1.0
#pragma parameter OLDTV_FRAME_LIMIT "OldTV Frame Limit" 0.16 0.0 1.0 0.01
#pragma parameter OLDTV_FRAME_SHAPE "OldTV Frame Shape" 0.44 0.0 1.0 0.01
#pragma parameter OLDTV_FRAME_SHARPNESS "OldTV Frame Sharpness" 0.80 0.0 10.0 0.01
#pragma parameter OLDTV_INTERFERENCE "OldTV Interference" 1.0 0.0 10.0 0.01

#ifdef PARAMETER_UNIFORM
uniform float OLDTV_CHROMA;
uniform float OLDTV_CHROMA_SHIFT;
uniform float OLDTV_USE_BARREL;
uniform float OLDTV_BARREL_VALUE;
uniform float OLDTV_BARREL_VALUE2;
uniform float OLDTV_USE_RAND;
uniform float OLDTV_USE_LUMA;
uniform float OLDTV_FRAME_LIMIT;
uniform float OLDTV_FRAME_SHAPE;
uniform float OLDTV_FRAME_SHARPNESS;
uniform float OLDTV_INTERFERENCE;
#else
#define OLDTV_CHROMA 4.0
#define OLDTV_CHROMA_SHIFT 2048
#define OLDTV_USE_BARREL 0
#define OLDTV_BARREL_VALUE 0.006
#define OLDTV_BARREL_VALUE2 0.5
#define OLDTV_USE_RAND 1
#define OLDTV_USE_LUMA 0
#define OLDTV_FRAME_LIMIT 0.16
#define OLDTV_FRAME_SHAPE 0.44
#define OLDTV_FRAME_SHARPNESS 0.80
#define OLDTV_INTERFERENCE 1.0
#endif

struct input
{
   float2 video_size;
   float2 texture_size;
   float2 output_size;
   float frame_count;
   float frame_direction;
   float frame_rotation;
};
     
struct VERTEX_OUTPUT {
   float4 position : POSITION;
   float4 vpos : TEXCOORD1;
   float2 texCoord : TEXCOORD0;
};
     
   VERTEX_OUTPUT main_vertex
(
 float4 position : POSITION,
 float2 texCoord : TEXCOORD0,
 float4 vpos : TEXCOORD1,
 uniform input IN,
 uniform float4x4 modelViewProj
 )
{
   VERTEX_OUTPUT OUT;
   OUT.position = mul(modelViewProj, position);
   OUT.vpos = OUT.position;
   OUT.texCoord = texCoord;
   return OUT;
}

struct output
{
   float4 color : COLOR;
};


float4 rgbdistort(float2 tc, sampler2D tex)
{
   float chroma = OLDTV_CHROMA;
   float shift = chroma / OLDTV_CHROMA_SHIFT;
   float red = tex2D(tex, tc+shift).r;
   float green = tex2D(tex,tc).g;
   float blue = tex2D(tex,tc-shift).b;
   return float4(red,green ,blue , 1.0);
}


float seed_random (float2 coords, float frame_cnt)
{
   frame_cnt = cos(frame_cnt);
   float2 constant1 = frame_cnt * float2(142.0/11.0, 1017.0/13.0);
   float constant2 = frame_cnt * 481344.0 / 11.0;
   return clamp(frac(sin(dot(coords, constant1)) * constant2) + 0.2, 0.0 ,1.0);
}

float2 barrelDistortion(float2 coord)
{
   float distortion = OLDTV_BARREL_VALUE;
   float2 cc = coord - OLDTV_BARREL_VALUE2;
   float dist = cc;
   return coord + cc * (dist + distortion * dist * dist) * distortion;
}

output main_fragment(in VERTEX_OUTPUT VAR, uniform sampler2D decal : TEXUNIT0, uniform input IN)
{
   //yes Cg is THIS retarded, passing position as texturecoord
   output OUT;
   VAR.vpos /= VAR.vpos.w;
   float2 p = VAR.texCoord;
   if (OLDTV_USE_BARREL == 1)
   {
      p = barrelDistortion(VAR.texCoord);
   }

   float rand = 1;

   float f = (1.0 - VAR.vpos.x *VAR.vpos.x) * (1.0 - VAR.vpos.y * VAR.vpos.y);
   float frame = clamp(OLDTV_FRAME_SHARPNESS * (pow(f, OLDTV_FRAME_SHAPE) - OLDTV_FRAME_LIMIT), 0.0, 1.0);

   if (OLDTV_USE_RAND == 1)
   {
      rand = seed_random(p, IN.frame_count);
   }

   if (OLDTV_USE_LUMA == 1)
   {
      float4 image = tex2D(decal,p);
      float luminance = dot(image.rgb, float3(0.299, 0.587, 0.114));
      image.rgb = float3(luminance,luminance,luminance);
      float4 distortion = rgbdistort(p,decal);
      OUT.color = frame * (OLDTV_INTERFERENCE *distortion*rand+ image);
   }
   else
   {
      float4 distortion = rgbdistort(p,decal);
      OUT.color = frame * (OLDTV_INTERFERENCE *distortion*rand);
   }

   return OUT;
}
