/*
   New MangaToon Shader v 1.1 + PSX OGL2 Noise v1.1

   Copyright (C) 2016-2018 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.
    
   Gold Noise ©2017-2018 dcerisano@standard3d.com 

   https://www.shadertoy.com/view/ltB3zD

    - based on the Golden Ratio, PI and Square Root of Two
    - fastest noise generator function
    - works with all chipsets (including low precision)

*/

uniform vec4 OGL2Param;
uniform vec4 OGL2Size;
uniform vec4 OGL2InvSize;
uniform sampler2D tex0;

float PHI = 1.61803398874989484820459 * 00000.1; // Golden Ratio   
float PI  = 3.14159265358979323846264 * 00000.1; // PI
float SQ2 = 1.41421356237309504880169 * 10000.0; // Square Root of Two

float gold_noise( vec2 coordinate, float seed){

	return fract(sin(dot(coordinate*(seed+PHI), vec2(PHI, PI)))*SQ2);

}

float CLength(vec3 c)
{
	float rmean = c.x*0.5;
	c*= c;
	return sqrt((2.0+rmean)*c.x+4.0*c.y+(3.0-rmean)*c.z)/3.0;
}

vec3 rgb_to_hsv(vec3 c)
{
	vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
	vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
	vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));

	float d = q.x - min(q.w, q.y);
	float e = 1.0e-10;
	return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}

vec3 hsv_to_rgb(vec3 c)
{
	vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
	vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
	return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

vec3 toon( vec3 c0 )
{
	c0 = rgb_to_hsv(c0);
	c0.b = min(1.0,(1.4+0.2*OGL2Param.z)*c0.b);
	return hsv_to_rgb(c0);
} 

void main (void)
{     
	vec3 c0 = toon(texture2D(tex0, gl_TexCoord[0].xy).rgb); 
	vec3 c1 = toon(texture2D(tex0, gl_TexCoord[0].xy + OGL2InvSize.xy * vec2( 0.0, 1.0)).rgb);
	vec3 c2 = toon(texture2D(tex0, gl_TexCoord[0].xy + OGL2InvSize.xy * vec2(-1.0, 1.0)).rgb);
	vec3 c3 = toon(texture2D(tex0, gl_TexCoord[0].xy + OGL2InvSize.xy * vec2(-1.0, 0.0)).rgb);
	vec3 c4 = toon(texture2D(tex0, gl_TexCoord[0].xy + OGL2InvSize.xy * vec2(-1.0,-1.0)).rgb);
	vec3 c5 = toon(texture2D(tex0, gl_TexCoord[0].xy + OGL2InvSize.xy * vec2( 0.0,-1.0)).rgb);
	vec3 c6 = toon(texture2D(tex0, gl_TexCoord[0].xy + OGL2InvSize.xy * vec2( 1.0,-1.0)).rgb);
	vec3 c7 = toon(texture2D(tex0, gl_TexCoord[0].xy + OGL2InvSize.xy * vec2( 1.0, 0.0)).rgb);
	vec3 c8 = toon(texture2D(tex0, gl_TexCoord[0].xy + OGL2InvSize.xy * vec2( 1.0, 1.0)).rgb);
            
	vec3 a0 = c8 - c4;
	vec3 a1 = a0 - c2 - 2.0 * c3 + c6 + 2.0 * c7;
	a0 = a0 + c2 + c1 * 2.0 - 2.0 * c5 - c6;

	a0 = a0 * a0 + a1 * a1;

	float ctoon = CLength(a0);
  
	c0 = c0-vec3(ctoon);

	float noise1 = gold_noise(gl_TexCoord[0].xy+0.5,(gl_TexCoord[0].x+0.5)*OGL2Size.x);
	float noise2 = gold_noise(gl_TexCoord[0].xy-0.5,(gl_TexCoord[0].x-0.5)*OGL2Size.x);
	float noise3 = gold_noise(gl_TexCoord[0].xy+0.5,(gl_TexCoord[0].y+0.5)*OGL2Size.y);
	float noise4 = gold_noise(gl_TexCoord[0].xy-0.5,(gl_TexCoord[0].y-0.5)*OGL2Size.y);

	gl_FragColor.rgb = vec3(min(min(noise1,noise2),min(noise3,noise4)))*c0+c0;

}

