////////////////////////////////////////////////////////
// GTU version 0.50
// Author: aliaspider - aliaspider@gmail.com
// License: GPLv3
////////////////////////////////////////////////////////

#pragma parameter noScanlines "No Scanlines" 0.0 0.0 1.0 1.0
#pragma parameter tvVerticalResolution "TV Vertical Resolution" 250.0 20.0 1000.0 10.0
#pragma parameter blackLevel "Black Level" 0.07 -0.30 0.30 0.01
#pragma parameter contrast "Contrast" 1.0 0.0 2.0 0.1
#ifdef PARAMETER_UNIFORM
uniform float noScanlines;
uniform float tvVerticalResolution;
uniform float blackLevel;
uniform float contrast;
#endif

#include "config.h"

#include "../../../compat_includes.inc"
uniform COMPAT_Texture2D(decal) : TEXUNIT0;
uniform float4x4 modelViewProj;

struct out_vertex
{
	float4 position : COMPAT_POS;
	float2 texCoord : TEXCOORD0;
#ifndef HLSL_4
	float4 Color    : COLOR;
#endif
};

out_vertex main_vertex(COMPAT_IN_VERTEX)
{
	out_vertex OUT;
#ifdef HLSL_4
	float4 position = VIN.position;
	float2 texCoord = VIN.texCoord;
#else
	OUT.Color = color;
#endif
	OUT.position = mul(modelViewProj, position);
	OUT.texCoord = texCoord;

	return OUT;
}

#define pi        3.14159265358
#define normalGauss(x) ((exp(-(x)*(x)*0.5))/sqrt(2.0*pi))

float normalGaussIntegral(float x)
{
   float a1 = 0.4361836;
   float a2 = -0.1201676;
   float a3 = 0.9372980;
   float p = 0.3326700;
   float t = 1.0 / (1.0 + p*abs(x));
   return (0.5-normalGauss(x) * (t*(a1 + t*(a2 + a3*t))))*sign(x);
}

float3 scanlines( float x , float3 c, float2 video_size, float2 output_size){
   float temp=sqrt(2*pi)*(tvVerticalResolution/video_size.y);

   float rrr=0.5*(video_size.y/output_size.y);
   float x1=(x+rrr)*temp;
   float x2=(x-rrr)*temp;
   c.r=(c.r*(normalGaussIntegral(x1)-normalGaussIntegral(x2)));
   c.g=(c.g*(normalGaussIntegral(x1)-normalGaussIntegral(x2)));
   c.b=(c.b*(normalGaussIntegral(x1)-normalGaussIntegral(x2)));
   c*=(output_size.y/video_size.y);
   return c;
}

#define Y(j) (offset.y-(j))
#define SOURCE(j) float2(texCoord.x,texCoord.y - Y(j)/texture_size.y)
#define C(j) (COMPAT_Sample(decal, SOURCE(j)).xyz)
#define VAL(j) (C(j)*STU(Y(j),(tvVerticalResolution/video_size.y)))
#define VAL_scanlines(j) (scanlines(Y(j),C(j), video_size, output_size))

float d(float x, float b)
{
	return pi*b*min(abs(x)+0.5,1.0/b);
}

float e(float x, float b)
{
	return (pi*b*min(max(abs(x)-0.5,-1.0/b),1.0/b));
}

float STU(float x, float b)
{
	return ((d(x,b)+sin(d(x,b))-e(x,b)-sin(e(x,b)))/(2.0*pi));
}

float4 pass_3(float2 texture_size, float2 video_size, float2 output_size, float2 texCoord, COMPAT_Texture2D(decal))
{
   float2   offset   = frac((texCoord.xy * texture_size.xy) - 0.5);
   float3   tempColor = float3(0,0,0);
   float3	Cj;

   float range=ceil(0.5+video_size.y/tvVerticalResolution);
   
   range = FIXNUM;

   float i;

   if (noScanlines)
      for (i=-range;i<range+2.0;i++){
         Cj = COMPAT_Sample(decal, float2(texCoord.x,texCoord.y - (offset.y-(i))/texture_size.y)).xyz;
		 tempColor += Cj*STU(offset.y-(i),(tvVerticalResolution/video_size.y));
      }
   else
      for (i=-range;i<range+2.0;i++){
         Cj = COMPAT_Sample(decal, float2(texCoord.x,texCoord.y - (offset.y-(i))/texture_size.y)).xyz;
		 tempColor += scanlines(offset.y - (i), Cj, video_size, output_size);
      }

   tempColor -= float3(blackLevel,blackLevel,blackLevel);
   tempColor *= (contrast/float3(1.0-blackLevel,1.0-blackLevel,1.0-blackLevel));
   return float4(tempColor, 1.0);
}

float4 main_fragment(COMPAT_IN_FRAGMENT) : COMPAT_Output
{
	return pass_3(COMPAT_texture_size, COMPAT_video_size, COMPAT_output_size, VOUT.texCoord, decal);
}
COMPAT_END
