#version 450

// NES CRT simulation (PAL)
// by r57shell
// https://www.shadertoy.com/view/MlsXWM
// WARNING: NOOB HERE :)
// Stream RU
// http://sc2tv.ru/channel/r57shell
// http://cybergame.tv/r57shell
// http://twitch.tv/elektropage

// some details
// http://forums.nesdev.com/viewtopic.php?f=3&t=12788&start=15

layout(push_constant) uniform Push
{
	vec4 SourceSize;
	vec4 OriginalSize;
	vec4 OutputSize;
	uint FrameCount;
} params;

layout(std140, set = 0, binding = 0) uniform UBO
{
	mat4 MVP;
} global;

#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;

void main()
{
   gl_Position = global.MVP * Position;
   vTexCoord = TexCoord * 1.00004;
}

#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;

#define iChannel0 Source
#define iResolution params.SourceSize
#define fragCoord vec2(vTexCoord.xy * params.OutputSize.xy)

vec2 size = params.SourceSize.xy;//vec2(320.,240.);
const float pi = 3.141592654;

vec3 monitor(vec2 p)
{
	vec2 pos = floor(p*size);
	vec2 uv = vTexCoord;// floor(pos)/size;
   	vec4 res = texture(iChannel0, uv);
    vec3 yuv = res.xyz*mat3(
        0.2126, 0.7152, 0.0722,
		-0.09991, -0.33609, 0.436,
		0.615, -0.55861, -0.05639);
    float alpha = (floor(p.x*size.x*4.)/2.0)*pi;
    vec2 sincv = vec2(cos(alpha), sin(alpha));
    if (mod(pos.y + 5.,4.) < 2.)
     sincv.x = -sincv.x;
    if (mod(pos.y, 4.) >= 2.)
     sincv.y = -sincv.y;
    float mc = 1.+dot(sincv, yuv.zy)/yuv.x;

    /*vec3 rgb = vec3(
        yuv.x + 1.28033 * yuv.z,
		yuv.x - 0.21482 * yuv.y - 0.38059 * yuv.z,
		yuv.x + 2.12798 * yuv.y);*/
    return res.xyz*mc;
}

// pos (left corner, sample size)
vec4 monitor_sample(vec2 p, vec2 tex_sample)
{
	// linear interpolation was...
    // now other thing.
    // http://imgur.com/m8Z8trV
    // AT LAST IT WORKS!!!!
    vec2 next = vec2(.25,1.)/size;
    vec2 f = fract(vec2(4.,1.)*size*p);
    tex_sample *= vec2(4.,1.)*size;
    vec2 l;
    vec2 r;
    if (f.x+tex_sample.x < 1.)
    {
       	l.x = f.x+tex_sample.x;
        r.x = 0.;
    }
    else
    {
        l.x = 1.-f.x;
        r.x = min(1.,f.x+tex_sample.x-1.);
    }
    if (f.y+tex_sample.y < 1.)
    {
       	l.y = f.y+tex_sample.y;
        r.y = 0.;
    }
    else
    {
        l.y = 1.-f.y;
        r.y = min(1.,f.y+tex_sample.y-1.);
    }
    vec3 top = mix(monitor(p),monitor(p+vec2(next.x,0.)),r.x/(l.x+r.x));
    vec3 bottom = mix(monitor(p+vec2(0.,next.y)),monitor(p+next),r.x/(l.x+r.x));
   	return vec4(mix(top,bottom,r.y/(l.y+r.y)),1.0);
    //difference should be only on border of pixels
    //return vec4((mix(top,bottom,r.y/(l.y+r.y)) - monitor(p))*2.+0.5,1.0);
}

void main()
{
	float zoom = 1.;
	FragColor = monitor_sample(vTexCoord, vec2(1.0));
}