/*
   SimoneT Bump Map + TV colors emulation  v.1.1

   Copyright (C) 2016 SimoneT - simone1tarditi@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 one       = vec3( 1.0 );

float CLength(vec4 c1){

	float rmean = c1.x*0.5;

	c1*= c1;

	return sqrt((2.0+rmean)*c1.x+4.0*c1.y+(3.0-rmean)*c1.z)/2.0;
}

vec3 Bump( vec2 texCoords, vec2 OGLParam, float normalStrength ){     

/*

	+----+----+----+----+----+
	| 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 |
	+----+----+----+----+----+

*/	
	vec4 color[25];
	color[0]  = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2(-2.0,-2.0));   
	color[1]  = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2(-1.0,-2.0));   
	color[2]  = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2( 0.0,-2.0));   
	color[3]  = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2( 1.0,-2.0));   
	color[4]  = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2( 2.0,-2.0));   

	color[5]  = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2(-2.0,-1.0));   
	color[6]  = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2(-1.0,-1.0));   
	color[7]  = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2( 0.0,-1.0));   
	color[8]  = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2( 1.0,-1.0));   
	color[9]  = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2( 2.0,-1.0));   

	color[10] = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2(-2.0, 0.0));   
	color[11] = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2(-1.0, 0.0));   
	color[12] = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2( 0.0, 0.0));   
	color[13] = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2( 1.0, 0.0));   
	color[14] = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2( 2.0, 0.0));   

	color[15] = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2(-2.0, 1.0));   
	color[16] = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2(-1.0, 1.0));   
	color[17] = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2( 0.0, 1.0));   
	color[18] = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2( 1.0, 1.0));   
	color[19] = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2( 2.0, 1.0));   

	color[20] = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2(-2.0, 2.0));   
	color[21] = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2(-1.0, 2.0));   
	color[22] = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2( 0.0, 2.0));   
	color[23] = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2( 1.0, 2.0));   
	color[24] = texture2D(OGL2Texture, gl_TexCoord[0].xy + OGLParam * vec2( 2.0, 2.0));   

/*

	+----+----+----+----+----+
	| 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 tl = CLength((color[0]  + 2.0 * color[1]  + color[2]  + 2.0 * color[5]  + 4.0 * color[6]  + 2.0 * color[7]  + color[10] + 2.0 * color[11] + color[12]) * 0.0625); // top left
	float  l = CLength((color[5]  + 2.0 * color[6]  + color[7]  + 2.0 * color[10] + 4.0 * color[11] + 2.0 * color[12] + color[15] + 2.0 * color[16] + color[17]) * 0.0625); // left
	float bl = CLength((color[10] + 2.0 * color[11] + color[12] + 2.0 * color[15] + 4.0 * color[16] + 2.0 * color[17] + color[20] + 2.0 * color[21] + color[22]) * 0.0625); // bottom left
	float  t = CLength((color[1]  + 2.0 * color[2]  + color[3]  + 2.0 * color[6]  + 4.0 * color[7]  + 2.0 * color[8]  + color[11] + 2.0 * color[12] + color[13]) * 0.0625); // top
	vec4   c =        ((color[6]  + 2.0 * color[7]  + color[8]  + 2.0 * color[11] + 4.0 * color[12] + 2.0 * color[13] + color[16] + 2.0 * color[17] + color[18]) * 0.0625); // center
	float  b = CLength((color[11] + 2.0 * color[12] + color[13] + 2.0 * color[16] + 4.0 * color[17] + 2.0 * color[18] + color[21] + 2.0 * color[22] + color[23]) * 0.0625); // bottom
	float tr = CLength((color[2]  + 2.0 * color[3]  + color[4]  + 2.0 * color[7]  + 4.0 * color[8]  + 2.0 * color[9]  + color[12] + 2.0 * color[13] + color[14]) * 0.0625); // top right
	float  r = CLength((color[7]  + 2.0 * color[8]  + color[9]  + 2.0 * color[12] + 4.0 * color[13] + 2.0 * color[14] + color[17] + 2.0 * color[18] + color[19]) * 0.0625); // right
	float br = CLength((color[12] + 2.0 * color[13] + color[14] + 2.0 * color[17] + 4.0 * color[18] + 2.0 * color[19] + color[22] + 2.0 * color[23] + color[24]) * 0.0625); // bottom right

	// Compute dx using Sobel:
	//           -1 0 1 
	//           -2 0 2
	//           -1 0 1

	float dX = (tr + 2.0*r + br -tl - 2.0*l - bl);

	// Compute dy using Sobel:
	//          -1 -2 -1 
	//           0  0  0
	//           1  2  1

	float dY = (bl + 2.0*b + br -tl - 2.0*t - tr);

	// Build the normalized normal

	//float normalStrength = 8.0;

	vec3 normal = normalize(vec3(dX, 1.0 / normalStrength, dY)) * 0.5 + 0.5;

	// Determine where the light is positioned (this can be set however you like)  

	vec3 light_pos = normalize(vec3(0.5, 1.5, 0.5));  
	
	// Calculate the lighting diffuse value  

	float diffuse = max(dot(normal, light_pos),0.0);  
 
	// Set the output color of our current pixel  

	return diffuse * c.rgb ;
}

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

/*

	+----+----+----+
	| 06 | 07 | 08 |
	+----+----+----+
	| 03 | 04 | 05 | 
	+----+----+----+
	| 00 | 01 | 02 |
	+----+----+----+

*/

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

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

	( swirl.x < 0.5 ) ?  (shift.x = shift.x) : (shift.x = -shift.x) ;
	( swirl.y < 0.5 ) ?  (shift.y = shift.y) : (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; 

	return clamp(0.0,1.0,ceil(dot(abs(a-b),one)+dot(abs(b-c),one)+dot(abs(c-d),one)));

}

// NTSC RGB to sRGB

vec3 ntscrgb_2_srgb( vec3 c ) {

	vec3 v = ( pow( c, vec3(2.2) ) *
        mat3(  0.6068909,  0.1735011,  0.2003480,
 	       0.2989164,  0.5865990,  0.1144845,
 	       0.0000000,  0.0660957,  1.1162243 ) ) *
	mat3(  3.2404542, -1.5371385, -0.4985314,
	      -0.9692660,  1.8760108,  0.0415560,
 	       0.0556434, -0.2040259,  1.0572252 );

	v.r = ( v.r > 0.0031308 ) ? (( 1.055 * pow( v.r, ( 1.0 / 2.4 ))) - 0.055 ) : 12.92 * v.r;
	v.g = ( v.g > 0.0031308 ) ? (( 1.055 * pow( v.g, ( 1.0 / 2.4 ))) - 0.055 ) : 12.92 * v.g;
	v.b = ( v.b > 0.0031308 ) ? (( 1.055 * pow( v.b, ( 1.0 / 2.4 ))) - 0.055 ) : 12.92 * v.b;

	return clamp( v, 0.0, 1.0 );
}
 
void main()
{

	float e = detect3d( gl_TexCoord[0].xy, Size3D, InvSize3D );

	vec2 pos3d = floor( gl_TexCoord[0].xy * Size3D );

	vec2 newsize3d = Size3D*OGL2Size.zw;

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

	     pos3d = ( pos3d + frac3d ) * InvSize3D;

	vec3 C0 = e * Bump( pos3d, InvSize3D, 8.0 );

	vec2 pos2d = floor( gl_TexCoord[0].xy * Size2D );

	vec2 newsize2d = Size2D*OGL2Size.zw;

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

	     pos2d = ( pos2d + frac2d ) * InvSize2D;

	vec3 C1 = ( 1.0 - e ) * Bump( pos2d, InvSize2D, 4.0 );

	gl_FragColor.rgb = ( ( 3.0 - OGL2Param.z ) * ntscrgb_2_srgb( C0 + C1 ) + OGL2Param.z * ( C0 + C1 ) )/3.0;

	//gl_FragColor.rgb = C0 + C1;

}
