/* COMPATIBILITY 
   - HLSL compilers
   - Cg   compilers
*/

/*
    cgwg's CRT shader

    Copyright (C) 2010-2011 cgwg, Themaister

    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the Free
    Software Foundation; either version 2 of the License, or (at your option)
    any later version.

    (cgwg gave their consent to have their code distributed under the GPL in
    this message:

        http://board.byuu.org/viewtopic.php?p=26075#p26075

        "Feel free to distribute my shaders under the GPL. After all, the
        barrel distortion code was taken from the Curvature shader, which is
        under the GPL."
    )
*/

#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 TEX2D(c) COMPAT_SamplePoint(s0 ,(c))
#define PI 3.141592653589

#pragma parameter CRTCGWG_GAMMA "CRTcgwg Gamma" 2.7 0.0 10.0 0.01

#ifdef PARAMETER_UNIFORM
uniform float CRTCGWG_GAMMA;
#else
#define CRTCGWG_GAMMA 2.7
#endif

float4 crt_cgwg_fast( COMPAT_Texture2D(s0), float2 texCoord, float2 texture_size, float2 video_size, float2 output_size)
{
   float2 delta = 1.0 / texture_size;
   float dx = delta.x;
   float dy = delta.y;
   
   float2 c01 = texCoord + float2(-dx, 0.0);
   float2 c11 = texCoord + float2(0.0, 0.0);
   float2 c21 = texCoord + float2(dx, 0.0);
   float2 c31 = texCoord + float2(2.0 * dx, 0.0);
   float2 c02 = texCoord + float2(-dx, dy);
   float2 c12 = texCoord + float2(0.0, dy);
   float2 c22 = texCoord + float2(dx, dy);
   float2 c32 = texCoord + float2(2.0 * dx, dy);
   float mod_factor = c11.x * output_size.x * texture_size.x / video_size.x;
   float2 ratio_scale = c11 * texture_size;
   
   float2 uv_ratio = frac(ratio_scale);
   float3 col, col2;

   float4x3 texes0 = float4x3(TEX2D(c01).xyz, TEX2D(c11).xyz, TEX2D(c21).xyz, TEX2D(c31).xyz);
   float4x3 texes1 = float4x3(TEX2D(c02).xyz, TEX2D(c12).xyz, TEX2D(c22).xyz, TEX2D(c32).xyz);

   float4 coeffs = float4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x) + 0.005;
   coeffs = sin(PI * coeffs) * sin(0.5 * PI * coeffs) / (coeffs * coeffs);
   coeffs = coeffs / dot(coeffs, float(1.0));

   float3 weights = float3(3.33 * uv_ratio.y, 3.33 * uv_ratio.y, 3.33 * uv_ratio.y);
   float3 weights2 = float3(uv_ratio.y * -3.33 + 3.33, uv_ratio.y * -3.33 + 3.33, uv_ratio.y * -3.33 + 3.33);

   col = saturate(mul(coeffs, texes0));
   col2 = saturate(mul(coeffs, texes1));

   float3 wid = 2.0 * pow(col, float3(4.0, 4.0, 4.0)) + 2.0;
   float3 wid2 = 2.0 * pow(col2, float3(4.0, 4.0, 4.0)) + 2.0;

   col = pow(col, float3(CRTCGWG_GAMMA, CRTCGWG_GAMMA, CRTCGWG_GAMMA));
   col2 = pow(col2, float3(CRTCGWG_GAMMA, CRTCGWG_GAMMA, CRTCGWG_GAMMA));

   float3 sqrt1 = rsqrt(0.5 * wid);
   float3 sqrt2 = rsqrt(0.5 * wid2);

   float3 pow_mul1 = weights * sqrt1;
   float3 pow_mul2 = weights2 * sqrt2;

   float3 div1 = 0.1320 * wid + 0.392;
   float3 div2 = 0.1320 * wid2 + 0.392;

   float3 pow1 = -pow(pow_mul1, wid);
   float3 pow2 = -pow(pow_mul2, wid2);

   weights = exp(pow1) / div1;
   weights2 = exp(pow2) / div2;

   float3 multi = col * weights + col2 * weights2;
   float3 mcol = lerp(float3(1.0, 0.7, 1.0), float3(0.7, 1.0, 0.7), floor(fmod(mod_factor, 2.0)));

   return float4(pow(mcol * multi, float3(0.454545, 0.454545, 0.454545)), 1.0);
}

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