/* COMPATIBILITY 
   - HLSL compilers
   - Cg   compilers
   - FX11
*/

/*
    zfast_crt_standard - A simple, fast CRT shader.
    Copyright (C) 2017 Greg Hogan (SoltanGris42)
    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.
Notes:  This shader does scaling with a weighted linear filter for adjustable
	sharpness on the x and y axes based on the algorithm by Inigo Quilez here:
	http://http://www.iquilezles.org/www/articles/texture/texture.htm
	but modified to be somewhat sharper.  Then a scanline effect that varies
	based on pixel brighness is applied along with a monochrome aperture mask.
	This shader runs at 60fps on the Raspberry Pi 3 hardware at 2mpix/s
	resolutions (1920x1080 or 1600x1200).
*/

//This can't be an option without slowing the shader down
//Comment this out for a coarser 3 pixel mask...which is currently broken
//on SNES Classic Edition due to Mali 400 gpu precision
#define FINEMASK
//Some drivers don't return black with texture coordinates out of bounds
//SNES Classic is too slow to black these areas out when using fullscreen
//overlays.  But you can uncomment the below to black them out if necessary
//#define BLACK_OUT_BORDER

#pragma parameter BLURSCALEX "Blur Amount X-Axis" 0.30 0.0 1.0 0.05
#pragma parameter LOWLUMSCAN "Scanline Darkness - Low" 6.0 0.0 10.0 0.5
#pragma parameter HILUMSCAN "Scanline Darkness - High" 8.0 0.0 50.0 1.0
#pragma parameter BRIGHTBOOST "Dark Pixel Brightness Boost" 1.25 0.5 1.5 0.05
#pragma parameter MASK_DARK "Mask Effect Amount" 0.25 0.0 1.0 0.05
#pragma parameter MASK_FADE "Mask/Scanline Fade" 0.8 0.0 1.0 0.05
#ifdef PARAMETER_UNIFORM
uniform float BLURSCALEX;
//uniform float BLURSCALEY;
uniform float LOWLUMSCAN;
uniform float HILUMSCAN;
uniform float BRIGHTBOOST;
uniform float MASK_DARK;
uniform float MASK_FADE;
#else
#define BLURSCALEX 0.45
//#define BLURSCALEY 0.20
#define LOWLUMSCAN 5.0
#define HILUMSCAN 10.0
#define BRIGHTBOOST 1.25
#define MASK_DARK 0.25
#define MASK_FADE 0.8
#endif

#include "../../compat_includes.inc"

// ************
// * UNIFORMS *
// ************

uniform float4x4 modelViewProj;
uniform COMPAT_Texture2D(decal);

// ***********
// * STRUCTS *
// ***********

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

// *****************
// * VERTEX SHADER *
// *****************

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;
   
   OUT.maskFade = 0.333 * MASK_FADE;
   OUT.invDims = 1.0 / COMPAT_texture_size.xy;

	return OUT;
}

// ****************
// * PIXEL SHADER *
// ****************

float4 zfast_crt(COMPAT_Texture2D(Source), float2 texture_size, float2 video_size, float2 output_size, float2 coord, float maskFade, float2 invDims)
{
   float2 gl_FragCoord = (coord * texture_size / video_size) * output_size;
	//This is just like "Quilez Scaling" but sharper
	vec2 p = coord * texture_size;
	vec2 i = floor(p) + 0.50;
	vec2 f = p - i;
	p = (i + 4.0*f*f*f)*invDims;
	p.x = mix( p.x , coord.x, BLURSCALEX);
	float Y = f.y*f.y;
	float YY = Y*Y;
	
#if defined(FINEMASK) 
	float whichmask = frac( gl_FragCoord.x*-0.4999);
	float mask = 1.0 + float(whichmask < 0.5) * -MASK_DARK;
#else
	float whichmask = frac(gl_FragCoord.x * -0.3333);
	float mask = 1.0 + float(whichmask <= 0.33333) * -MASK_DARK;
#endif
	float3 colour = COMPAT_Sample(Source, p).rgb;
	
	float scanLineWeight = (BRIGHTBOOST - LOWLUMSCAN*(Y - 2.05*YY));
	float scanLineWeightB = 1.0 - HILUMSCAN*(YY-2.8*YY*Y);	
	
#if defined(BLACK_OUT_BORDER)
	colour.rgb*=float(tc.x > 0.0)*float(tc.y > 0.0); //why doesn't the driver do the right thing?
#endif

   return float4(colour.rgb*mix(scanLineWeight*mask, scanLineWeightB, dot(colour.rgb,float3(maskFade,maskFade,maskFade))), 1.0);
}
   
float4 main_fragment(COMPAT_IN_FRAGMENT) : COMPAT_Output
{
	return zfast_crt(decal, COMPAT_texture_size, COMPAT_video_size, COMPAT_output_size, VOUT.texCoord, VOUT.maskFade, VOUT.invDims);
}
COMPAT_END