/*
 *  HDR2SDR.frag
 *  HexelPaint
 *
 *  Created by Kenneth Kopecky on 9/26/11.
 *  Copyright 2011 Orange Element Studios. All rights reserved.
 *
 */

#extension GL_ARB_texture_rectangle : enable
#extension GL_EXT_texture_rectangle : enable
vec4 deHDR(vec4 hdr)
{
	//divide by the highest value component (or 1, if they're all less than 1)
	float most = max(hdr.r, max(hdr.g, max(1.0, hdr.b)));

	hdr.rgb /= most;
	hdr.a = min(hdr.a, 1.0);
	return hdr;
}

uniform ivec2 viewportSize;
uniform sampler2DRect inputTex;
uniform sampler2DRect glowTex;
uniform int glowSizeFactor;
uniform float SDRConversionAmount;
uniform float glowMult;		//for inverting the glow
uniform vec4 canvasColor;
uniform float testMode;
uniform float hexelOpacity;
uniform mat4x4 colorMatrix;		//for hue shifting
uniform float saturation;
uniform float brightness;

float glowAlpha;		//how much glow there is, based on its color

vec4 colorProcess(vec4 color);

vec4 additiveGlow(vec4 tex, vec4 glow)
{
	//pre-add factor is how much of the texture we add to glow before downsampling (we'll add the rest later)
	float preAddFactor = glowAlpha * 0.5 * (0.5 + 0.5 * glowMult);		//0.5 for additive, 0 for subtractive

	//add the pre-add in
	glow.rgb += tex.rgb * preAddFactor * glowMult * tex.a;

	//de-HDR it
	vec4 sdrglow = deHDR(glow);
	glow = mix(glow, sdrglow, SDRConversionAmount);

	float alphaAdjust = mix(1.0, tex.a, min(glowAlpha, 1.0));	//if there's glow, multiply our result by the texture's alpha
//	alphaAdjust = 0.0;
//	tex.rgb += glow.rgb;
//	return tex;
	vec4 result = glow * glowMult + tex * (1.0 - preAddFactor) * alphaAdjust;
	return result;

}

vec4 subtractiveGlow(vec4 tex, vec4 glow)
{
	//for subtractive glow, we need to use the canvas color first
	tex.rgb = mix(tex.rgb, canvasColor.rgb, 1.0 - tex.a);
	vec4 sdrglow = mix(glow, deHDR(glow), SDRConversionAmount);
	vec4 ntex = tex;
	ntex.rgb -= glow.rgb;//sdrglow.rgb;
	ntex = max(ntex, 0.0);
	return ntex;
}

vec4 subtractiveGlow2(vec4 tex, vec4 glow)
{
	vec4 sdrglow = mix(glow, deHDR(glow), SDRConversionAmount);
	sdrglow.rgb = vec3(0.0) - sdrglow.rgb;
//	return glow;
//	if(sdrglow.g < 0.0)
//		return vec4(0.5, 0.5, 0.5, 1.0);
	if(sdrglow.g > 0.0)
		return vec4(1.0, 1.0, 1.0, 1.0);
	return tex + sdrglow;
	return sdrglow * tex;
	return tex * sdrglow;
}


void main()
{
	vec4 otex = texture2DRect(inputTex, gl_TexCoord[0].xy);
//	otex.a *= hexelOpacity;
	//pull the alpha out.  it'll be multiplied back in in a bit
//	if(otex.a > 0.001)
//		otex.rgb /= otex.a;
	vec2 glowTexCoord = gl_TexCoord[0].xy;
 //	glowTexCoord = clamp(glowTexCoord, vec2(glowSizeFactor), vec2(viewportSize - glowSizeFactor*2));
	glowTexCoord /= float(glowSizeFactor);
	vec4 glow = texture2DRect(glowTex, glowTexCoord);
//	glow = vec4(0.0);
	glowAlpha = max(glow.r, max(glow.g, glow.b));		//the effective alpha of the glow (only for the background)
	glowAlpha = min(glowAlpha, 1.0 + 100.0 * testMode);
	
	//modify the glow color so that it reflects the canvas color if nothing is behind the glow
	vec4 oglow = glow;

	//non-transparent canvas,blend with the canvas color
	vec4 modTex = otex;

	//de-alpha our color once to restore to the original one we drew
//	modTex.a = sqrt(modTex.a);
	vec4 demodColor = canvasColor;
//	demodColor = vec4(0.0);			//this introduced haloing, switching it back
	float demodAlpha = modTex.a;
//	demodAlpha = sqrt(demodAlpha);
	modTex.rgb = (modTex.rgb - demodColor.rgb * (1.0 - demodAlpha)) / max(demodAlpha, 0.01);		//undo our alpha blending from the clearColor!
	vec4 mod2 = modTex;

	//this seems to destroy our AA ):
//	if(testMode > 0.5)
//	{
//		mod2.rgb = (modTex.rgb - demodColor.rgb * (1.0 - demodAlpha)) / max(demodAlpha, 0.01);		//undo our alpha blending again!
//	}
	//if we don't have a transparent canvas, do the blending right now
	vec4 adjustedInput = mod2;
	modTex = mod2;
	modTex.rgb = mix(modTex.rgb, canvasColor.rgb, (1.0-modTex.a) * canvasColor.a);
	modTex.a = max(modTex.a, canvasColor.a);
//	modTex.rgb /= modTex.a;	//undo our alpha blending!
//	if(canvasColor.a > 0.002)
	{
//		modTex.rgb = mix(canvasColor.rgb, modTex.rgb, modTex.a);
//		modTex.a = 1.0;
	}
	
	vec4 additive = additiveGlow(modTex, glow);
//	additive = modTex;
    vec4 subtractive = subtractiveGlow(modTex, glow);
//	subtractive = vec4(1.0, 0.0, 0.0, 1.0);
	gl_FragColor = mix(additive, subtractive, 0.5 - glowMult * 0.5);

//	if(gl_FragColor.g > otex.g)
//		gl_FragColor = vec4(.5, .5, .5, 1.0);
//	if(gl_FragCoord.x > 500.0)
//		gl_FragColor.rgb = deHDR(glow).rgb;
	gl_FragColor.a = min(gl_FragColor.a, 1.0);
	//if(gl_FragCoord.x < 300.0)
	//	gl_FragColor.rgb = otex.rgb;
//	gl_FragColor.rgb = vec3(1.0) - deHDR(glow).rgb * glowMult;
	
	gl_FragColor.a = 1.0;

	gl_FragColor.a = min(modTex.a, 1.0);
	gl_FragColor.a = max(gl_FragColor.a, glowAlpha);
	gl_FragColor.a = min(gl_FragColor.a, 1.0);
 
//	gl_FragColor.rgb = vec3(glowAlpha);
//	gl_FragColor = otex;
//	gl_FragColor.r = 0.0;= 1.0;
//	gl_FragColor.rgb = glow.rgb;
//	gl_FragColor.b = 1.0;
//	gl_FragColor.rgb = otex.rgb * otex.a + glow.rgb;
//	gl_FragColor = glow;
//	gl_FragColor.rgb = vec3(otex.a);
//	gl_FragColor.rgb /= glow.a;
//	gl_FragColor.a = 1.0;
//	gl_FragColor.rgb = vec3(1.0)-glow.rgb;
//	modTex = mix(modTex, canvasColor, 1.0 - modTex.a);
// 
	//do alpha blending here
//	gl_FragColor.rgb = mix(gl_FragColor.rgb, canvasColor.rgb, (1.0-gl_FragColor.a) * canvasColor.a);
#ifdef DEBUG_MODE
	if(gl_FragCoord.y < 800)
	{
		gl_FragColor.rgb = colorProcess(gl_FragColor).rgb;
//		gl_FragColor = hueShift(gl_FragColor, (float(gl_FragCoord.y - 500))/57.3);
	}
	

#endif
//	gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}



vec4 colorProcess(vec4 color)
{
	//hue shift comes with a matrix transform
	color.rgb = (colorMatrix * color).rgb;
	//saturation pulls the color to zero
	vec3 toGrey = vec3(.299, .587, .114);
	float grey = dot(color.rgb, toGrey);
	color.rgb = mix(color.rgb, vec3(grey), 1.0 - saturation);
	
    return color;
}
