/*
   New Bump Shader 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.
    
*/

#version 130

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

vec4 cubic(float v){
	vec4 n = vec4(1.0, 2.0, 3.0, 4.0) - v;
	vec4 s = n * n * n;
	float x = s.x;
	float y = s.y - 4.0 * s.x;
	float z = s.z - 4.0 * s.y + 6.0 * s.x;
	float w = 6.0 - x - y - z;
	return vec4(x, y, z, w) * (1.0/6.0);
}

vec3 Bicubic(vec2 Coords, vec2 texSize, vec2 invTexSize ){

	vec2 texCoords = Coords * texSize - 0.5;
   
	vec2 fxy = fract(texCoords);
	texCoords -= fxy;

	vec4 xcubic = cubic(fxy.x);
	vec4 ycubic = cubic(fxy.y);

	vec4 c = texCoords.xxyy + vec2(-0.5, +1.5).xyxy;
    
	vec4 s = vec4(xcubic.xz + xcubic.yw, ycubic.xz + ycubic.yw);
	vec4 offset = c + vec4(xcubic.yw, ycubic.yw) / s;
    
	offset *= invTexSize.xxyy;
    
	vec3 c0 = texture(OGL2Texture, offset.xz).rgb;
	vec3 c1 = texture(OGL2Texture, offset.yz).rgb;
	vec3 c2 = texture(OGL2Texture, offset.xw).rgb;
	vec3 c3 = texture(OGL2Texture, offset.yw).rgb;

	float sx = s.x / (s.x + s.y);
	float sy = s.z / (s.z + s.w);

	return mix(mix(c3, c2, sx), mix(c1, c0, sx), sy);

}

vec3 Bump( vec2 texCoords, vec2 Size, vec2 InvSize ){     

	float tl  = length(Bicubic( texCoords - InvSize                    , Size, InvSize ));   
	float t   = length(Bicubic( texCoords - vec2(       0.0, InvSize.y), Size, InvSize ));   
	float tr  = length(Bicubic( texCoords - vec2(-InvSize.x, InvSize.y), Size, InvSize ));   

	float l   = length(Bicubic( texCoords - vec2( InvSize.x,       0.0), Size, InvSize ));   
	vec3  c   =        Bicubic( texCoords,                               Size, InvSize  );   
	float r   = length(Bicubic( texCoords + vec2( InvSize.x,       0.0), Size, InvSize ));   

	float bl  = length(Bicubic( texCoords + vec2(-InvSize.x, InvSize.y), Size, InvSize ));   
	float b   = length(Bicubic( texCoords + vec2(       0.0, InvSize.y), Size, InvSize ));   
	float br  = length(Bicubic( texCoords + InvSize,                     Size, InvSize ));

	// 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 = 4.0 + 4.0 * OGL2Param.z;

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

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

	vec3 light_pos = normalize(vec3(0.25, 0.5, 0.75));  
	
	// 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;

}

void main()
{

	gl_FragColor.rgb = Bump( gl_TexCoord[0].xy, OGL2Size.xy, OGL2InvSize.xy );

}
