/*
   Manga shader v 1.0

   Copyright (C) 2016-2017 SimoneT - simone1tarditi@gmail.com

   part of the code taken from "Directional Cubic Convolution Interpolation"
   created by Dengwen Zhou and Xiaoliu Shen.

   https://en.wikipedia.org/wiki/Directional_Cubic_Convolution_Interpolation

   de Blur - Copyright (C) 2016 guest(r) - guest.r@gmail.com

   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.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    
*/

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

varying vec2 v_texCoord;
uniform sampler2D Frame;

//const   vec4 Size = vec4( 1024.0, 512.0, 0.0009765625, 0.001953125 );
const   vec4 Size = vec4( 2048.0, 1024.0, 0.00048828125, 0.0009765625 );

const   mat3 RGBtoYIQ = mat3(0.299, 0.596, 0.212, 
                             0.587,-0.275,-0.523, 
                             0.114,-0.321, 0.311);

const   mat3 YIQtoRGB = mat3(1.0, 1.0, 1.0,
                             0.95568806036115671171,-0.27158179694405859326,-1.1081773266826619523,
                             0.61985809445637075388,-0.64687381613840131330, 1.7050645599191817149);

const   vec3 val00 = vec3( 1.2, 1.2, 1.2);

const	vec4 exp = vec4(30.0);	

float CLength(vec3 c1){

	float rmean = c1.r*0.5;

	c1*= c1;

	return sqrt((2.0+rmean)*c1.r+4.0*c1.g+(3.0-rmean)*c1.b);
}

float Cdistance(vec3 c1, vec3 c2){

	float rmean = (c1.r+c2.r)*0.5;

	c1 = pow(c1-c2,vec3(2.0));

	return sqrt((2.0+rmean)*c1.r+4.0*c1.g+(3.0-rmean)*c1.b);
}

vec3 ColMin(vec3 a, vec3 b){

	float dist = step(0.01,sign(CLength(a) - CLength(b)));

	return mix(a,b,dist);

}

vec3 ColMax(vec3 a, vec3 b){

	float dist = step(0.01,sign(CLength(a) - CLength(b)));

	return mix(b,a,dist);

}

vec3 Interpolate( vec3 a, vec3 b ) {

	return ( a + b ) * 0.5;

}

vec3 STGRAA2D( vec2 coord, vec4 texSize ) {

	vec2 frac = fract(v_texCoord*texSize.xy);
	vec2 TexCoord = (floor(coord*texSize.xy)+0.5)*texSize.zw;
	vec4 shift  = vec4( texSize.zw,-texSize.zw);
	vec4 shift2 = 2.0*shift;

	vec3 C00 = texture2D(Frame, TexCoord + shift2.zw                ).rgb;
	vec3 C01 = texture2D(Frame, TexCoord + vec2( shift.z , shift2.w)).rgb;
	vec3 C02 = texture2D(Frame, TexCoord + vec2( 0.0     , shift2.w)).rgb;
	vec3 C03 = texture2D(Frame, TexCoord + vec2( shift.x , shift2.w)).rgb;
	vec3 C04 = texture2D(Frame, TexCoord + vec2( shift2.x, shift2.w)).rgb;

	vec3 C05 = texture2D(Frame, TexCoord + vec2( shift2.z, shift.w )).rgb;
	vec3 C06 = texture2D(Frame, TexCoord + shift.zw                 ).rgb;
	vec3 C07 = texture2D(Frame, TexCoord + vec2( 0.0     , shift.w )).rgb;
	vec3 C08 = texture2D(Frame, TexCoord + vec2( shift.x , shift.w )).rgb;
	vec3 C09 = texture2D(Frame, TexCoord + vec2( shift2.x, shift.w )).rgb;

	vec3 C10 = texture2D(Frame, TexCoord + vec2( shift2.z, 0.0     )).rgb;
	vec3 C11 = texture2D(Frame, TexCoord + vec2( shift.z , 0.0     )).rgb;
	vec3 C12 = texture2D(Frame, TexCoord                            ).rgb;
	vec3 C13 = texture2D(Frame, TexCoord + vec2( shift.x , 0.0     )).rgb;
	vec3 C14 = texture2D(Frame, TexCoord + vec2( shift2.x, 0.0     )).rgb;

	vec3 C15 = texture2D(Frame, TexCoord + vec2( shift2.z, shift.y )).rgb;
	vec3 C16 = texture2D(Frame, TexCoord + vec2( shift.z , shift.y )).rgb;
	vec3 C17 = texture2D(Frame, TexCoord + vec2( 0.0     , shift.y )).rgb;
	vec3 C18 = texture2D(Frame, TexCoord + shift.xy                 ).rgb;
	vec3 C19 = texture2D(Frame, TexCoord + vec2( shift2.x, shift.y )).rgb;

	vec3 C20 = texture2D(Frame, TexCoord + vec2( shift2.z, shift2.y)).rgb;
	vec3 C21 = texture2D(Frame, TexCoord + vec2( shift.z , shift2.y)).rgb;
	vec3 C22 = texture2D(Frame, TexCoord + vec2( 0.0     , shift2.y)).rgb;
	vec3 C23 = texture2D(Frame, TexCoord + vec2( shift.x , shift2.y)).rgb;
	vec3 C24 = texture2D(Frame, TexCoord + shift2.xy                ).rgb;

	float C03C09 = Cdistance(C03,C09);
	float C02C08 = Cdistance(C02,C08);
	float C08C14 = Cdistance(C08,C14);
	float C01C07 = Cdistance(C01,C07);
	float C07C13 = Cdistance(C07,C13);
	float C13C19 = Cdistance(C13,C19);
	float C00C06 = Cdistance(C00,C06);
	float C06C12 = Cdistance(C06,C12);
	float C12C18 = Cdistance(C12,C18);
	float C18C24 = Cdistance(C18,C24);
	float C05C11 = Cdistance(C05,C11);
	float C11C17 = Cdistance(C11,C17);
	float C17C23 = Cdistance(C17,C23);
	float C10C16 = Cdistance(C10,C16);
	float C16C22 = Cdistance(C16,C22);
	float C15C21 = Cdistance(C15,C21);

	vec4 d01 = vec4(
	C02C08 + C01C07 + C07C13 + C00C06 + C06C12 + C12C18 + C05C11 + C11C17 + C10C16,
	C03C09 + C02C08 + C08C14 + C01C07 + C07C13 + C13C19 + C06C12 + C12C18 + C11C17,
	C07C13 + C06C12 + C12C18 + C05C11 + C11C17 + C17C23 + C10C16 + C16C22 + C15C21,
	C08C14 + C07C13 + C13C19 + C06C12 + C12C18 + C18C24 + C11C17 + C17C23 + C16C22);

	d01 = pow(d01,exp)+1.0;

	float C01C05 = Cdistance(C01,C05);
	float C02C06 = Cdistance(C02,C06);
	float C06C10 = Cdistance(C06,C10);
	float C03C07 = Cdistance(C03,C07);
	float C07C11 = Cdistance(C07,C11);
	float C11C15 = Cdistance(C11,C15);
	float C04C08 = Cdistance(C04,C08);
	float C08C12 = Cdistance(C08,C12);
	float C12C16 = Cdistance(C12,C16);
	float C16C20 = Cdistance(C16,C20);
	float C09C13 = Cdistance(C09,C13);
	float C13C17 = Cdistance(C13,C17);
	float C17C21 = Cdistance(C17,C21);
	float C14C18 = Cdistance(C14,C18);
	float C18C22 = Cdistance(C18,C22);
	float C19C23 = Cdistance(C19,C23);

	vec4 d02 = vec4(
	C01C05 + C02C06 + C06C10 + C03C07 + C07C11 + C11C15 + C08C12 + C12C16 + C13C17,
	C02C06 + C03C07 + C07C11 + C04C08 + C08C12 + C12C16 + C09C13 + C13C17 + C14C18,
	C06C10 + C07C11 + C11C15 + C08C12 + C12C16 + C16C20 + C13C17 + C17C21 + C18C22,
	C07C11 + C08C12 + C12C16 + C09C13 + C13C17 + C17C21 + C14C18 + C18C22 + C19C23);

	d02 = pow(d02,exp)+1.0;

	vec4 w01 = 1.0 / d01;
	vec4 w02 = 1.0 / d02;
	vec4 w03 = w01 + w02;
	     w03 = 1.0 / w03;

	vec4 weight01 = w01 * w03;
	vec4 weight02 = w02 * w03;

	vec3 DR0 = Interpolate( C06, C12 ); 
	vec3 UR0 = Interpolate( C07, C11 ); 

	vec3 DR1 = Interpolate( C07, C13 ); 
	vec3 UR1 = Interpolate( C08, C12 ); 

	vec3 DR2 = Interpolate( C11, C17 ); 
	vec3 UR2 = Interpolate( C12, C16 ); 

	vec3 DR3 = Interpolate( C12, C18 ); 
	vec3 UR3 = Interpolate( C13, C17 ); 

	vec3 sum0 = DR0 * weight01.x + UR0 * weight02.x; 
	vec3 sum1 = DR1 * weight01.y + UR1 * weight02.y;
	vec3 sum2 = DR2 * weight01.z + UR2 * weight02.z;
	vec3 sum3 = DR3 * weight01.w + UR3 * weight02.w;

	return mix(mix(sum0,sum1,frac.x),mix(sum2,sum3,frac.x),frac.y);
 
}

vec3 Blur( vec2 TexCoord ) {

	vec2 shift  = Size.zw * 0.5;

	vec3 C06 = texture2D(Frame, TexCoord - shift.xy).rgb;
	vec3 C07 = texture2D(Frame, TexCoord + vec2( shift.x,-shift.y)).rgb;
	vec3 C11 = texture2D(Frame, TexCoord + vec2(-shift.x, shift.y)).rgb;
	vec3 C12 = texture2D(Frame, TexCoord + shift.xy).rgb;

	float dif1 = Cdistance(C06,C12) + 0.00001;
	float dif2 = Cdistance(C07,C11) + 0.00001;
 
	float filterparam = 7.0; // de Blur control

	dif1=pow(dif1,filterparam);
	dif2=pow(dif2,filterparam);

	float dif3=dif1+dif2; 
 
	return (dif1*(C07+C11)*0.5 + dif2*(C06+C12)*0.5)/dif3;

}

//      de Blur code

vec3 deBlur(vec3 C9) {

	vec2 dx = vec2( Size.z,    0.0);
	vec2 dy = vec2(    0.0, Size.w);
	vec2 g1 = vec2( Size.z, Size.w);
	vec2 g2 = vec2(-Size.z, Size.w);

	vec3 C0 = Blur( v_texCoord-g1).rgb; 
	vec3 C1 = Blur( v_texCoord-dy).rgb;
	vec3 C2 = Blur( v_texCoord-g2).rgb;
	vec3 C3 = Blur( v_texCoord-dx).rgb;
	vec3 C4 = Blur( v_texCoord   ).rgb;
	vec3 C5 = Blur( v_texCoord+dx).rgb;
	vec3 C6 = Blur( v_texCoord+g2).rgb;
	vec3 C7 = Blur( v_texCoord+dy).rgb;
	vec3 C8 = Blur( v_texCoord+g1).rgb;

	vec3 mn1 = ColMin(ColMin(C0,C1),C2);
	vec3 mn2 = ColMin(ColMin(C3,C4),C5);
	vec3 mn3 = ColMin(ColMin(C6,C7),C8);
	     mn1 = ColMin(ColMin(mn1,mn2),mn3);

	vec3 mx1 = ColMax(ColMax(C0,C1),C2);
	vec3 mx2 = ColMax(ColMax(C3,C4),C5);
	vec3 mx3 = ColMax(ColMax(C6,C7),C8);
 	     mx1 = ColMax(ColMax(mx1,mx2),mx3);

	float dif1 = Cdistance(C9,mn1) + 0.00001;
	float dif2 = Cdistance(C9,mx1) + 0.00001;
 
	float filterparam = 7.0; // de Blur control

	dif1=pow(dif1,filterparam);
	dif2=pow(dif2,filterparam);

	float dif3=dif1+dif2; 
 
	return (dif1*mx1 + dif2*mn1)/dif3;

}

void main()
{

	vec3 C0 = deBlur(STGRAA2D( v_texCoord, Size ));
	//vec3 C0 = deBlur(Blur( v_texCoord ));
	vec3 yiq = RGBtoYIQ * C0;
	vec3 rgb = YIQtoRGB * vec3(smoothstep(0.0,0.9,yiq.x), yiq.yz * val00.yz);

	gl_FragColor.rgb = C0;//rgb;

}
