
uniform sampler2D texture;
uniform float hsv_h, hsv_s, hsv_v;

vec3 rgb2hsv(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 hsv2rgb(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);
}






void main(void) {
	vec2 xy = gl_TexCoord[0].xy;
	vec4 col =  texture2D(texture,xy);
	vec3 hsv = rgb2hsv(col.rgb)+vec3(hsv_h,0,hsv_v);
	vec3 rgb = hsv2rgb(hsv);
	float grayscale = (rgb.r + rgb.g + rgb.b)/3.0f;
	vec3 v3 = rgb.rgb *vec3(hsv_s)+vec3(grayscale*(1.0-hsv_s));
	vec4 result = vec4(v3, col.a);
	gl_FragColor = result;
}


// unoptimized variants
/*
vec4 rgb2hsv(vec3 c) {
	float M,m;
	vec4 ret = vec4(0);
	M = max(c.r,max(c.g,c.b));
	m = min(c.r,min(c.g,c.b));
	float C = M - m;
	float h2 = 0.0;
	if(M == c.r) {
		h2 = mod(((c.g-c.b)/C),6);
	}
	else if(M == c.g) {
		h2 = (c.b-c.r)/C + 2.0;
	}
	else if(M == c.b) {
		h2 = (c.r-c.g)/C + 4.0;
	}
	ret.r = (h2*60.0)/360;


	if(ret.r == 0.0) {
		ret.g = 0;
	} else {
		ret.g = C/M; 
	}
	ret.b = M;
	
	return ret;	
}

vec4 hsv2rgb(vec3 rgb) {
	 vec3 ret;
	 float V = rgb.b;
	 float S = rgb.g;
	 float C = V * S;
	 float H = (rgb.r)*360;
	 float h2 = H/60.0;
	 float X = C*(1-abs( mod(h2,2) - 1));
	if(h2 < 0 ) 
		ret = vec3(0,0,0);
	else if (h2 < 1)
		ret = vec3(C,X,0);
	else if (h2 < 2)
		ret = vec3(X,C,0);
	else if (h2 < 3)
		ret = vec3(0,C,X);	
	else if (h2 < 4)
		ret = vec3(0,X,C);
	else if (h2 < 5)
		ret = vec3(X,0,C);	
	else if (h2 < 6)
		ret = vec3(C,0,X);	
		
	float m = V-C;	
	return vec4(ret.r+m, ret.g+m,ret.b+m,1.0);
}
*/