/*
   SimoneT mixed 3D/2D games Shader v 1.9  ( fast version )

   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 

   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 one       = vec3( 1.0 );

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;

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

	return e;

}

vec3 Interpolate( vec3 a, vec3 b ) {

	return ( a + b )  * 0.5 ;
}

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

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

/*

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

*/

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

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

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

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

/*

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

*/

	float C02C08 = Cdistance(C02,C08);
	float C01C07 = Cdistance(C01,C07);
	float C07C13 = Cdistance(C07,C13);
	float C00C06 = Cdistance(C00,C06);
	float C06C12 = Cdistance(C06,C12);
	float C12C18 = Cdistance(C12,C18);
	float C05C11 = Cdistance(C05,C11);
	float C11C17 = Cdistance(C11,C17);
	float C10C16 = Cdistance(C10,C16);

/*

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

*/

	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 C08C12 = Cdistance(C08,C12);
	float C12C16 = Cdistance(C12,C16);
	float C13C17 = Cdistance(C13,C17);

/*

	+----+----+----+
	| 10 | 11 | 12 |
	+----+----+----+
	| 05 | 06 | 07 |
	+----0----+----+
	| 00 | 01 | 02 |
	+----+----+----+

*/

	vec4 d01;
	vec4 d02;

	    d01.x = C01C07 + 
	            C00C06 + C06C12 +
	            C05C11 ;

	    d02.x = C01C05 + 
	  	    C02C06 + C06C10 + 
	            C07C11 ;

/*

	+----+----+----+
	| 11 | 12 | 13 |
	+----+----+----+
	| 06 | 07 | 08 |
	+----1----+----+
	| 01 | 02 | 03 |
	+----+----+----+

*/

	    d01.y = C02C08 + 
	            C01C07 + C07C13 +
	            C06C12 ;

	    d02.y = C02C06 + 
	  	    C03C07 + C07C11 + 
	            C08C12 ;

/*

	+----+----+----+
	| 15 | 16 | 17 |
	+----+----+----+
	| 10 | 11 | 12 |
	+----2----+----+
	| 05 | 06 | 07 |
	+----+----+----+


*/

	    d01.z = C06C12 + 
	            C05C11 + C11C17 +
	            C10C16 ;

	    d02.z = C06C10 + 
	  	    C07C11 + C11C15 + 
	            C12C16 ;

/*

	+----+----+----+
	| 16 | 17 | 18 |
	+----+----+----+
	| 11 | 12 | 13 |
	+----3----+----+
	| 06 | 07 | 08 |
	+----+----+----+

*/

	    d01.w = C07C13 + 
	            C06C12 + C12C18 +
	            C11C17 ;

	    d02.w = C07C11 + 
	  	    C08C12 + C12C16 + 
	            C13C17 ;

	vec4 w01 = 1.0 / (1.0 + pow(d01,vec4(15.0)));
	vec4 w02 = 1.0 / (1.0 + pow(d02,vec4(15.0)));

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

	vec3 DR0 = Interpolate( C00, C06 ); 
	vec3 UR0 = Interpolate( C01, C05 ); 

	vec3 DR1 = Interpolate( C01, C07 ); 
	vec3 UR1 = Interpolate( C02, C06 ); 

	vec3 DR2 = Interpolate( C05, C11 ); 
	vec3 UR2 = Interpolate( C06, C10 ); 

	vec3 DR3 = Interpolate( C06, C12 ); 
	vec3 UR3 = Interpolate( C07, C11 ); 

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

void main()
{

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

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

}
