NAMESPACE_ENTER(CFX)

#include "ReShade/ioFX.cfg"

#if USE_HighPassSharpening == 1
//High Pass Sharpening & Contrast Enhancement
//Version 1.2
/* This shader uses the gaussian blur passes from Boulotaur2024's gaussian blur/ bloom, unsharpmask shader which are based
   on the implementation in the article "Efficient Gaussian blur with linear sampling"
   http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/ .
   The blend modes are based on algorithms found at http://www.dunnbypaul.net/blends/ , 
   http://www.deepskycolors.com/archive/2010/04/21/formulas-for-Photoshop-blending-modes.html ,
   http://www.simplefilter.de/en/basics/mixmods.html and http://en.wikipedia.org/wiki/Blend_modes . 
   For more info go to http://reshade.me/forum/shader-presentation/529-high-pass-sharpening */ 
#define CoefLuma_HP float3(0.2126, 0.7152, 0.0722)

float3 brgb2hsv(float3 rgb) {
    float minValue = min(min(rgb.r, rgb.g), rgb.b);
    float maxValue = max(max(rgb.r, rgb.g), rgb.b);
    float d = maxValue - minValue;

    float3 hsv = 0.0;
    hsv.b = maxValue;
    if (d != 0) {
        hsv.g = d / maxValue;

        float3 delrgb = (((maxValue.xxx - rgb) / 6.0) + d / 2.0) / d;
        if      (maxValue == rgb.r) { hsv.r = delrgb.b - delrgb.g; }
        else if (maxValue == rgb.g) { hsv.r = 1.0 / 3.0 + delrgb.r - delrgb.b; }
        else if (maxValue == rgb.b) { hsv.r = 2.0 / 3.0 + delrgb.g - delrgb.r; }

        if (hsv.r < 0.0) { hsv.r += 1.0; }
        if (hsv.r > 1.0) { hsv.r -= 1.0; }
    }
    return hsv;
}

float3 bhsv2rgb(float3 hsv) {
    const float h = hsv.r, s = hsv.g, v = hsv.b;

    float3 rgb = v;
    if (hsv.g != 0.0) {
        float h_i = floor(6 * h);
        float f = 6 * h - h_i;

        float p = v * (1.0 - s);
        float q = v * (1.0 - f * s);
        float t = v * (1.0 - (1.0 - f) * s);

        if      (h_i == 0) { rgb = float3(v, t, p); }
        else if (h_i == 1) { rgb = float3(q, v, p); }
        else if (h_i == 2) { rgb = float3(p, v, t); }
        else if (h_i == 3) { rgb = float3(p, q, v); }
        else if (h_i == 4) { rgb = float3(t, p, v); }
        else               { rgb = float3(v, p, q); }
    }
    return rgb;
}

float4 SharpBlurFinal(in float4 pos : SV_Position, in float2 texcoord : TEXCOORD) : COLOR
{
	#define PX_SIZE (RFX_PixelSize/SharpPrecision)

	float4 color = tex2D(RFX_backbufferColor, texcoord);
	
	float sampleOffsetsX[25] = {  0.0, 	   1, 	  0, 	 1,     1,     2,     0,     2,     2,     1,    -1,     2,     2,     3,     0,     3,     3,     1,    -1, 3, 3, 2, 2, 3, 3 };
	float sampleOffsetsY[25] = {  0.0,     0, 	  1, 	 1,    -1,     0,     2,     1,    -1,     2,     2,     2,    -2,     0,     3,     1,    -1,     3,     3, 2, -2, 3, -3, 3, -3};
	float sampleWeights[25] = { 0, 0.125, 0.125, 0.125, 0.125, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.04167, 0.04167, 0.04167, 0.04167, 0.04167, 0.04167, 0.04167, 0.04167, 0.04167, 0.04167, 0.04167, 0.04167 };
	//0.172+0.109+0.109+0.068+0.068+0.020+0.020+0.012+0.012+0.012+0.012+0.002+0.002+0.001+0.001+0.001+0.001+0.001+0.001
	#if SharpRadius == 0
		#define SamplesHP 5
	#elif SharpRadius == 1
		#define SamplesHP 13
	#else 
		#define SamplesHP 25
	#endif

	[loop]
	for(int i = 1; i < SamplesHP; ++i) {
			color += tex2D(RFX_backbufferColor, texcoord + float2(sampleOffsetsX[i] * PX_SIZE.x, sampleOffsetsY[i] * PX_SIZE.y)) * sampleWeights[i];
			color += tex2D(RFX_backbufferColor, texcoord - float2(sampleOffsetsX[i] * PX_SIZE.x, sampleOffsetsY[i] * PX_SIZE.y)) * sampleWeights[i];
		}
	#if SharpRadius == 0
	color *= 0.5;
	#elif SharpRadius == 1 
	color *= 0.33333;
	#else 
		color *= 0.25;
	#endif

	float4 orig = tex2D(RFX_backbufferColor, texcoord); //Original Image
	#define ltest 1
#if ltest == 0
	orig.rgb = brgb2hsv(orig.rgb);
	color.rgb = brgb2hsv(color.rgb);
	float luma = orig.b;
	float2 chroma = orig.rg;
	float sharp = 1 - color.b;
	sharp = (luma + sharp)*0.5;
#else
	float luma = max(orig.r,max(orig.g,orig.b));
	float3 chroma = orig.rgb - luma;
	float sharp = 1 - max(color.r,max(color.g,color.b));
	sharp = (luma + sharp)*0.5;
#endif

	float sharpMin = min(0.5,(DarkLineIntensity*(sharp - 0.5)*(sharp+0.5))+0.5);
	float sharpMax = max(0.5,(LightLineIntensity*(sharp - 0.5)*(sharp+0.5))+0.5);
	sharp = lerp(sharpMin,sharpMax,step(0.5,sharp));
			
			#if ViewSharpMask == 1
				orig.rgb = sharp;
				luma = sharp;
			#elif BlendMode == 3
				//Multiply
				sharp = 2 * luma * sharp;
			#elif BlendMode == 6
				//Screen
				sharp = 1.0 - (2*(1.0-luma)*(1.0-sharp));
				//sharp = luma+2*sharp-1;
			#elif BlendMode == 7
				//Linear Light
				sharp = lerp(luma+2*sharp-1,luma+2*(sharp-0.5),step(0.5,sharp));
				//sharp = luma+2*sharp-1;
				//sharp = luma+2*(sharp-0.5);
			#elif BlendMode == 2
				//overlay
				sharp = lerp(2*luma*sharp, 1.0 - 2*(1.0-luma)*(1.0-sharp), step(0.5,luma));
			#elif BlendMode == 4
				//Hardlight
				sharp = lerp(2*luma*sharp, 1.0 - 2*(1.0-luma)*(1.0-sharp), step(0.5,sharp));
			#elif BlendMode == 1 
				//softlight
				//sharp = lerp(2*luma*color.rgb + luma*luma*(1.0-2*color.rgb), 2*luma*(1.0-sharp)+pow(luma,0.5)*(2*sharp-1.0), smoothstep(0.0,0.49,sharp.rgb));
				//sharp = lerp(2*luma*sharp + luma*luma*(1.0-2*sharp), 2*luma*(1.0-sharp)+pow(luma,0.5)*(2*sharp-1.0), step(0.49,sharp.rgb));
				sharp = lerp((2*sharp-1)*(luma-pow(luma,2))+luma, ((2*sharp-1)*(pow(luma,0.5)-luma))+luma, step(0.49,sharp));
			#elif BlendMode == 5
				//vivid light
				//sharp = lerp(1-(1-luma)/(2*sharp), luma/(2*(1-sharp)), step(0.5,sharp));
				sharp = lerp(1-(1-luma)/(2*sharp), luma/(2*(1-sharp)), smoothstep(0.49,0.5,luma));
			#endif
		
		
		
		#if ViewSharpMask == 1

		#else
			#if ltest == 0
			orig.b = lerp(luma, sharp, HPSharpStrength);
			orig.rgb = float3(chroma,orig.b);
			orig.rgb = bhsv2rgb(orig.rgb);
			#else
			orig.rgb = lerp(luma, sharp, HPSharpStrength);
			orig.rgb += chroma;
			#endif
		#endif
	return saturate(orig);
}


technique HighPassSharp <bool enabled = RFX_Start_Enabled; int toggle = HighPass_ToggleKey; >
{

	pass Sharp
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = SharpBlurFinal;
	}

}
#endif

#include "ReShade/ioFX.undef"

NAMESPACE_LEAVE()

#pragma message "ioFX 1.1 by Ioxa\n\n"
