/*
   SimoneT mixed 3D - 2D games Shader v 1.9 WIP

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

   part of 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, 4xGLSoft lite - 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.
    
*/

uniform sampler2D OGL2Texture;
uniform vec4 OGL2Size;
uniform vec4 OGL2InvSize;
uniform vec4 OGL2Param;

const   vec2 Size2D    = vec2( 2048.0, 1024.0 );
const   vec2 InvSize2D = 1.0/vec2( 2048.0, 1024.0 );
const   vec2 Size3D    = vec2( 4096.0, 2048.0);
const   vec2 InvSize3D = 1.0/vec2( 4096.0, 2048.0 );
const   vec3 ones = vec3( 1.0, 1.0, 1.0 );
const   float gamma = 1.0 / 2.4;
const	float X = 9.0;
const	float Y = 1.0;
const	float Z = 0.05;
const	float exp = 15;	

float Cdistance(vec3 c1, vec3 c2){

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

	vec3 c3  = c1 - c2;

	     c3 *= c3;

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

}
 
float detect3d( vec2 texCoords, vec2 texSize, vec2 shift ){

	vec2 pos = (floor(texCoords*texSize)+0.5)*shift;

	vec2 swirl = fract((texCoords*texSize)*0.5);

	shift.x = ( swirl.x < 0.5 ) ? ( shift.x ) : ( -shift.x ) ;
	shift.y = ( swirl.y < 0.5 ) ? ( shift.y ) : ( -shift.y ) ;

	vec3 a = texture2D(OGL2Texture, pos                        ).rgb;
	vec3 b = texture2D(OGL2Texture, pos + vec2( shift.x, 0.0 ) ).rgb;
	vec3 c = texture2D(OGL2Texture, pos + vec2( 0.0, shift.y ) ).rgb;
	vec3 d = texture2D(OGL2Texture, pos + shift                ).rgb; 

	float e;

	e = ( a == b && b == c && c == d ) ? ( 0.0 ) : ( 1.0 ) ;

	return e;

}

vec3 Interpolate( vec3 a, vec3 b, vec3 c, vec3 d ) {

	return ( X * ( a + b ) + Y * ( c + d ) ) * Z;

}

vec3 Diagonal( vec2 coord, vec2 texSize, vec2 shift ) {

	vec2 TexCoord = (floor(coord*texSize)+0.5)*shift;

/*

	+----+----+----+----+----+
	| 20 | 21 | 22 | 23 | 24 |
	+----+----+----+----+----+
	| 15 | 16 | 17 | 18 | 19 |
	+----+----2----3----+----+
	| 10 | 11 | 12 | 13 | 14 |
	+----+----0----1----+----+
	| 05 | 06 | 07 | 08 | 09 |
	+----+----+----+----+----+
	| 00 | 01 | 02 | 03 | 04 |
	+----+----+----+----+----+

*/

	vec3 C00 = texture2D(OGL2Texture, TexCoord + shift * vec2(-2.0,-2.0)).rgb;
	vec3 C01 = texture2D(OGL2Texture, TexCoord + shift * vec2(-1.0,-2.0)).rgb;
	vec3 C02 = texture2D(OGL2Texture, TexCoord + shift * vec2( 0.0,-2.0)).rgb;
	vec3 C03 = texture2D(OGL2Texture, TexCoord + shift * vec2( 1.0,-2.0)).rgb;
	vec3 C04 = texture2D(OGL2Texture, TexCoord + shift * vec2( 2.0,-2.0)).rgb;

	vec3 C05 = texture2D(OGL2Texture, TexCoord + shift * vec2(-2.0,-1.0)).rgb;
	vec3 C06 = texture2D(OGL2Texture, TexCoord + shift * vec2(-1.0,-1.0)).rgb;
	vec3 C07 = texture2D(OGL2Texture, TexCoord + shift * vec2( 0.0,-1.0)).rgb;
	vec3 C08 = texture2D(OGL2Texture, TexCoord + shift * vec2( 1.0,-1.0)).rgb;
	vec3 C09 = texture2D(OGL2Texture, TexCoord + shift * vec2( 2.0,-1.0)).rgb;

	vec3 C10 = texture2D(OGL2Texture, TexCoord + shift * vec2(-2.0, 0.0)).rgb;
	vec3 C11 = texture2D(OGL2Texture, TexCoord + shift * vec2(-1.0, 0.0)).rgb;
	vec3 C12 = texture2D(OGL2Texture, TexCoord + shift * vec2( 0.0, 0.0)).rgb;
	vec3 C13 = texture2D(OGL2Texture, TexCoord + shift * vec2( 1.0, 0.0)).rgb;
	vec3 C14 = texture2D(OGL2Texture, TexCoord + shift * vec2( 2.0, 0.0)).rgb;

	vec3 C15 = texture2D(OGL2Texture, TexCoord + shift * vec2(-2.0, 1.0)).rgb;
	vec3 C16 = texture2D(OGL2Texture, TexCoord + shift * vec2(-1.0, 1.0)).rgb;
	vec3 C17 = texture2D(OGL2Texture, TexCoord + shift * vec2( 0.0, 1.0)).rgb;
	vec3 C18 = texture2D(OGL2Texture, TexCoord + shift * vec2( 1.0, 1.0)).rgb;
	vec3 C19 = texture2D(OGL2Texture, TexCoord + shift * vec2( 2.0, 1.0)).rgb;

	vec3 C20 = texture2D(OGL2Texture, TexCoord + shift * vec2(-2.0, 2.0)).rgb;
	vec3 C21 = texture2D(OGL2Texture, TexCoord + shift * vec2(-1.0, 2.0)).rgb;
	vec3 C22 = texture2D(OGL2Texture, TexCoord + shift * vec2( 0.0, 2.0)).rgb;
	vec3 C23 = texture2D(OGL2Texture, TexCoord + shift * vec2( 1.0, 2.0)).rgb;
	vec3 C24 = texture2D(OGL2Texture, TexCoord + shift * vec2( 2.0, 2.0)).rgb;

/*

	+----+----+----+----+----+
	| 20 | 21 | 22 | 23 | 24 |
	+----/----/----/----/----+
	| 15 | 16 | 17 | 18 | 19 |
	+----/----/----/----/----+
	| 10 | 11 | 12 | 13 | 14 |
	+----/----/----/----/----+
	| 05 | 06 | 07 | 08 | 09 |
	+----/----/----/----/----+
	| 00 | 01 | 02 | 03 | 04 |
	+----+----+----+----+----+

*/

	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);

/*

	+----+----+----+----+----+
	| 20 | 21 | 22 | 23 | 24 |
	+----\----\----\----\----+
	| 15 | 16 | 17 | 18 | 19 |
	+----\----\----\----\----+
	| 10 | 11 | 12 | 13 | 14 |
	+----\----\----\----\----+
	| 05 | 06 | 07 | 08 | 09 |
	+----\----\----\----\----+
	| 00 | 01 | 02 | 03 | 04 |
	+----+----+----+----+----+

*/

	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);

/*


	+----+----+----+----+
	| 15 | 16 | 17 | 18 |
	+----+----+----+----+
	| 10 | 11 | 12 | 13 |
	+----+----0----+----+
	| 05 | 06 | 07 | 08 |
	+----+----+----+----+
	| 00 | 01 | 02 | 03 |
	+----+----+----+----+

*/

	vec4 d01;
	vec4 d02;

	    d01.x = C02C08 + 
	  	    C01C07 + C07C13 + 
	            C00C06 + C06C12 + C12C18 +
	            C05C11 + C11C17 + 
	            C10C16 ;

	    d02.x = C01C05 + 
	  	    C02C06 + C06C10 + 
	            C03C07 + C07C11 + C11C15 +
	            C08C12 + C12C16 + 
	            C13C17 ;

/*

	+----+----+----+----+
	| 16 | 17 | 18 | 19 |
	+----+----+----+----+
	| 11 | 12 | 13 | 14 |
	+----+----1----+----+
	| 06 | 07 | 08 | 09 |
	+----+----+----+----+
	| 01 | 02 | 03 | 04 |
	+----+----+----+----+

*/

	    d01.y = C03C09 + 
	  	    C02C08 + C08C14 + 
	            C01C07 + C07C13 + C13C19 +
	            C06C12 + C12C18 + 
	            C11C17 ;

	    d02.y = C02C06 + 
	  	    C03C07 + C07C11 + 
	            C04C08 + C08C12 + C12C16 +
	            C09C13 + C13C17 + 
	            C14C18 ;

/*

	+----+----+----+----+
	| 20 | 21 | 22 | 23 |
	+----+----+----+----+
	| 15 | 16 | 17 | 18 |
	+----+----2----+----+
	| 10 | 11 | 12 | 13 |
	+----+----+----+----+
	| 05 | 06 | 07 | 08 |
	+----+----+----+----+


*/

	    d01.z = C07C13 + 
	  	    C06C12 + C12C18 + 
	            C05C11 + C11C17 + C17C23 +
	            C10C16 + C16C22 + 
	            C15C21 ;

	    d02.z = C06C10 + 
	  	    C07C11 + C11C15 + 
	            C08C12 + C12C16 + C16C20 +
	            C13C17 + C17C21 + 
	            C18C22 ;

/*

	+----+----+----+----+
	| 21 | 22 | 23 | 24 |
	+----+----+----+----+
	| 16 | 17 | 18 | 19 |
	+----+----3----+----+
	| 11 | 12 | 13 | 14 |
	+----+----+----+----+
	| 06 | 07 | 08 | 09 |
	+----+----+----+----+

*/

	    d01.w = C08C14 + 
	  	    C07C13 + C13C19 + 
	            C06C12 + C12C18 + C18C24 +
	            C11C17 + C17C23 + 
	            C16C22 ;

	    d02.w = C07C11 + 
	  	    C08C12 + C12C16 + 
	            C09C13 + C13C17 + C17C21 +
	            C14C18 + C18C22 + 
	            C19C23 ;
	
	vec4 w01 = 1.0 / (1.0 + pow(d01,vec4(exp)));
	vec4 w02 = 1.0 / (1.0 + pow(d02,vec4(exp)));

	vec4 weight01 = w01 / (w01 + w02);
	vec4 weight02 = w02 / (w01 + w02);

	vec3 DR0 = Interpolate( C06, C12, C00, C18 ); 
	vec3 UR0 = Interpolate( C07, C11, C03, C15 ); 

	vec3 DR1 = Interpolate( C07, C13, C01, C19 ); 
	vec3 UR1 = Interpolate( C08, C12, C04, C16 ); 

	vec3 DR2 = Interpolate( C11, C17, C05, C23 ); 
	vec3 UR2 = Interpolate( C12, C16, C08, C20 ); 

	vec3 DR3 = Interpolate( C12, C18, C06, C24 ); 
	vec3 UR3 = Interpolate( C13, C17, C09, C21 ); 

	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;

	vec2 newsize = texSize*OGL2Size.zw;

	vec2 frac = fract(vec2(gl_TexCoord[1].x,1.0-gl_TexCoord[1].y)*newsize);

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

//	4xGLSoft lite code

vec4 yx = vec4(1.0/4096,1.0/2048,-1.0/4096,-1.0/2048);
vec4 xy = vec4(2.0/4096,2.0/2048,-2.0/4096,-2.0/2048);

vec3 texture2d (vec2 texcoord) {

	vec3 c11 = texture2D(OGL2Texture, texcoord        ).xyz; 
	vec3 c00 = texture2D(OGL2Texture, texcoord + xy.zw).xyz; 
	vec3 c20 = texture2D(OGL2Texture, texcoord + xy.xw).xyz; 
	vec3 c22 = texture2D(OGL2Texture, texcoord + xy.xy).xyz; 
	vec3 c02 = texture2D(OGL2Texture, texcoord + xy.zy).xyz; 
	vec3 s00 = texture2D(OGL2Texture, texcoord + yx.zw).xyz; 
	vec3 s20 = texture2D(OGL2Texture, texcoord + yx.xw).xyz; 
	vec3 s22 = texture2D(OGL2Texture, texcoord + yx.xy).xyz; 
	vec3 s02 = texture2D(OGL2Texture, texcoord + yx.zy).xyz; 

	vec3 dt = vec3(1.0,1.0,1.0);

	float d1=dot(abs(c00-c22),dt)+0.001;
	float d2=dot(abs(c20-c02),dt)+0.001;
	float m1=dot(abs(s00-s22),dt)+0.001;
	float m2=dot(abs(s02-s20),dt)+0.001;

	vec3 t2=(d1*(c20+c02)+d2*(c00+c22))/(2.0*(d1+d2));
	
	return .25*(c11+t2+(m2*(s00+s22)+m1*(s02+s20))/(m1+m2));
}

void main()
{

	float e  = detect3d( gl_TexCoord[0].xy, Size2D, InvSize2D );

	vec3 c11 = ( e < 1.0 ) ? ( Diagonal( gl_TexCoord[0].xy, Size2D, InvSize2D ) ) : 
					 ( Diagonal( gl_TexCoord[0].xy, Size3D, InvSize3D ) ) ;

//      de Blur code

	vec2 inv_size = vec2(0.00048828125, 0.0009765625);

	vec2 dx  = vec2(inv_size.x,0.0);
	vec2 dy  = vec2(0.0,inv_size.y);
	vec2 g1  = vec2( inv_size.x,inv_size.y);
	vec2 g2  = vec2(-inv_size.x,inv_size.y);
	vec2 pC4 = gl_TexCoord[0].xy;
  
	vec3 C0 = texture2d(pC4-g1); 
	vec3 C1 = texture2d(pC4-dy);
	vec3 C2 = texture2d(pC4-g2);
	vec3 C3 = texture2d(pC4-dx);
	vec3 C4 = texture2d(pC4   );
	vec3 C5 = texture2d(pC4+dx);
	vec3 C6 = texture2d(pC4+g2);
	vec3 C7 = texture2d(pC4+dy);
	vec3 C8 = texture2d(pC4+g1);

	vec3 mn1 = min(min(C0,C1),C2);
	vec3 mn2 = min(min(C3,C4),C5);
	vec3 mn3 = min(min(C6,C7),C8);
	vec3 mx1 = max(max(C0,C1),C2);
	vec3 mx2 = max(max(C3,C4),C5);
	vec3 mx3 = max(max(C6,C7),C8);
 
	mn1 = min(min(mn1,mn2),mn3);
	mx1 = max(max(mx1,mx2),mx3);
 
	vec3 dif1 = abs(c11-mn1) + 0.001*ones;
	vec3 dif2 = abs(c11-mx1) + 0.001*ones;
 
	float filterparam = 2.0; // de Blur control

	dif1=vec3(pow(dif1.x,filterparam),pow(dif1.y,filterparam),pow(dif1.z,filterparam));
	dif2=vec3(pow(dif2.x,filterparam),pow(dif2.y,filterparam),pow(dif2.z,filterparam));
 
	c11.r = (dif1.x*mx1.x + dif2.x*mn1.x)/(dif1.x + dif2.x);
	c11.g = (dif1.y*mx1.y + dif2.y*mn1.y)/(dif1.y + dif2.y);
	c11.b = (dif1.z*mx1.z + dif2.z*mn1.z)/(dif1.z + dif2.z);

	gl_FragColor.rgb = c11;

}
