   /*-----------------------------------------------------------.   
  /                       GEM                                /
  '-----------------------------------------------------------*/

/*
by Lucifer Hawk
Using algorithms from Christian Cann Schuldt Jensen ~ CeeJay.dk
*/

Texture2D srcTex;
Texture3D noiseTex;

#if (USE_SHADER3VERSION == 0)
SamplerState LinearSamplerWrap {
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
    AddressW = Wrap;
};
#endif

#define sharp_strength 0.45   
#define sharp_clamp    0.035  
#define pattern 2   
#define offset_bias 1.0                    
#define show_sharpen 0 
#if (USE_LUMASHARPEN == 0)
#include "SweetFX\Shaders\LumaSharpen.h"
#endif

	float GStrenght 	= 0.65;	//1.5		
	float GBaseGamma 	= 1.65;			
	float GFade		= 0.165;	//0.03	
	float GContrast		= 1.005;			
	float GSaturation	= 0.155;			
	float GBleach		= -0.20; 	
	float GRedCurve		= 6.0;			
	float GGreenCurve	= 6.0;			
	float GBlueCurve	= 6.0;			
	float GBaseCurve	= 1.5;			
	float GEffectGammaR	= 1.0;			
	float GEffectGammaG	= 1.0;			
	float GEffectGammaB	= 1.0;			
	float GEffectGamma	= 0.75;			
	float GLinearization	= 1.3;			

float GGetLuminance(float3 sample)
	 {
		 return dot(sample.xyz, 0.333);
	 }

#define Vibrance GSat
#define dither_method 1
#if (USE_VIBRANCE == 0)
  #include "SweetFX\Shaders\Vibrance.h"
#endif

float4 GEMTrueColor( float4 colorInput, float2 tex )
{
	
	#if (SSAO == 1)
	float3 CoefLuma2 = float3(0.2126, 0.7152, 0.0722);  //Values to calculate luma with
  
  	float diff1 = dot(CoefLuma2,myTex2D(s0, tex + pixel).rgb);
  	diff1 = dot(float4(CoefLuma2,-1.0),float4(myTex2D(s0, tex - pixel).rgb , diff1));
  	
  	float diff2 = dot(CoefLuma2,myTex2D(s0, tex +float2(pixel.x,-pixel.y)).rgb);
  	diff2 = dot(float4(CoefLuma2,-1.0),float4(myTex2D(s0, tex +float2(-pixel.x,pixel.y)).rgb , diff2));
    
  	float edge = dot(float2(diff1,diff2),float2(diff1,diff2));
  	
  	colorInput.rgb =  pow(edge,0.40) * -0.15 + colorInput.rgb;
	
  	colorInput = saturate(colorInput); 
	#endif	

	colorInput.rgb = (colorInput.rgb  - (3/255.0)) * (255.0/(255.0-8));

	float3 c_center = myTex2D(s0, tex).rgb; //reuse SMAA center sample or lumasharpen center sample?
	
	float radius1 = 0.793;
	float3 bloom_sum1 = myTex2D(s0, tex + float2(1.5, -1.5) * radius1).rgb;
	bloom_sum1 += myTex2D(s0, tex + float2(-1.5, -1.5) * radius1).rgb; //rearrange sample order to minimize ALU and maximize cache usage
	bloom_sum1 += myTex2D(s0, tex + float2(1.5, 1.5) * radius1).rgb;
	bloom_sum1 += myTex2D(s0, tex + float2(-1.5, 1.5) * radius1).rgb;
	
	bloom_sum1 += myTex2D(s0, tex + float2(0, -2.5) * radius1).rgb;
	bloom_sum1 += myTex2D(s0, tex + float2(0, 2.5) * radius1).rgb;
	bloom_sum1 += myTex2D(s0, tex + float2(-2.5, 0) * radius1).rgb;
	bloom_sum1 += myTex2D(s0, tex + float2(2.5, 0) * radius1).rgb;
	
	bloom_sum1 *= 0.005;
	
	float3 bloom_sum2 = myTex2D(s0, tex + float2(1.5, -1.5) * 0.75).rgb;
	bloom_sum2 += myTex2D(s0, tex + float2(-1.5, -1.5) * 0.75).rgb;
	bloom_sum2 += myTex2D(s0, tex + float2(1.5, 1.5) * 0.75).rgb;
	bloom_sum2 += myTex2D(s0, tex + float2(-1.5, 1.5) * 0.75).rgb;


	bloom_sum2 += myTex2D(s0, tex + float2(0, -2.5) * 0.75).rgb;	
	bloom_sum2 += myTex2D(s0, tex + float2(0, 2.5) * 0.75).rgb;
	bloom_sum2 += myTex2D(s0, tex + float2(-2.5, 0) * 0.75).rgb;
	bloom_sum2 += myTex2D(s0, tex + float2(2.5, 0) * 0.75).rgb;

	bloom_sum2 *= 0.010;
	
	float dist = 0.75 - radius1;
	
	float3 HDR = (c_center + (bloom_sum2 - bloom_sum1)) * dist;
	float3 blend = HDR + colorInput.rgb;
	colorInput.rgb = HDR + pow(blend, 1.02); // pow - don't use fractions for HDRpower
	
	colorInput = saturate(colorInput);	
	#if (SSAO == 1)
	colorInput = LumaSharpenPass(colorInput,tex);
	#endif
	colorInput = pow(colorInput, 1.23);	

	float4 B = colorInput;
	float3 coord=0.0;
	coord.xy=tex.xy;

	float2 offset[8]=
{
 float2(2.0, 2.0),
 float2(-2.0, -2.0),
 float2(-2.0, 2.0),
 float2(2.0, -2.0),

 float2(2.41, 0.0),
 float2(-2.41, 0.0),
 float2(0.0, 2.41),
 float2(0.0, -2.41)
};
int i=0;

float4 tcol=colorInput; //tex2Dlod(GSamplerColor, coord)
float invscreensize=0;
for (i=0; i<4; i++)
{
 float2 tdir=offset[i].xy;
 coord.xy=tex.xy+tdir.xy*invscreensize*1.0;
 float4 ct=colorInput; //tex2Dlod(GSamplerColor, coord)

 tcol+=ct;
}
tcol*=1.0/(3.8);

B = tcol;		

B = pow(B, 1/GTBright);

float GDefog=0.000; 					
float4 GFogColor={0.0, 0.0, 0.0, 0.0}; 			
float GExposure=0.000; 					
float GGamma=1.65; 					
float GBlueShift=0.0;

B.xyz = max(0, B.xyz - GDefog * GFogColor.xyz);
B.xyz *= pow(2.0f, GExposure);
B.xyz = pow(B.xyz, GGamma);
float3 trollface = B.xyz * float3(1.05f, 0.97f, 1.27f);
B.xyz = lerp(B.xyz, trollface, GBlueShift);

	#define GLUM_FACTOR float4(0.299, 0.187, 0.114, 0.0)
	float pixelLumi = dot(B.xyz, GLUM_FACTOR.xyz);
	float toneMapCalc = pixelLumi / (pixelLumi + 1);
	B =  toneMapCalc * pow(B / pixelLumi, 0.77);
	B = pow(B, 0.90);
	B = B * 1.3; //EXP

	float origgray=max(B.x, B.y);
	origgray=max(origgray, B.z);
	coord.xy=tex.xy*16.0 + origgray;

#if (USE_SHADER3VERSION == 0)
	float cnoi = noiseTex.Sample(LinearSamplerWrap, coord).r;
	B=lerp(B, (cnoi+GCBright)*B, 3.5*saturate(1.0-origgray*1.8));
#endif

#if (USE_SHADER3VERSION == 1)
	B=lerp(B, (0.035+GCBright)*B, 3.5*saturate(1.0-origgray*1.8));
#endif

	//float cnoi = noiseTex.Sample(LinearSampler, coord).r;
	//float4 cnoi=MyTex2D(SamplerNoise, coord.x); //colorInput;
	//B=lerp(B, (0.1+GCBright)*B, 3.5*saturate(1.0-origgray*1.8));

	float CrossContrast =1.002;		
	float CrossSaturation2 = 1.05;	
	float CrossBrightness = 0.017;		
	float CrossAmount = 3.0;		
	float2 crossMatrix [3] =
		{
			float2 (0.94, 0.0),
			float2 (0.96, 0.0),
			float2 (1.04, 0.0)
		};

		float4 image1 = B;
		float4 image2 = B;
		float gray = dot(float3(0.5,0.5,0.5), image1);

		image1 = lerp (gray, image1,CrossSaturation2);

		image1 = lerp (0.35, image1,CrossContrast);

		image1 +=CrossBrightness;
		image1 *=1.1;

		image2.r = image1.r * crossMatrix[0].x + crossMatrix[0].y;
		image2.g = image1.g * crossMatrix[1].x + crossMatrix[1].y;
		image2.b = image1.b * crossMatrix[2].x + crossMatrix[2].y;

		B = lerp(image1, image2, CrossAmount);

        float4 G = B;
	float4 H = 0.01;
 
	B = pow(abs(B), GLinearization);
	B = lerp(H, B, GContrast);
 
	float A = GGetLuminance(B.rgb);
	float4 D = A;
 
	B = pow(abs(B), 1.0 / GBaseGamma);
 
	float a = GRedCurve;
	float b = GGreenCurve;
	float c = GBlueCurve;
	float d = GBaseCurve;
 
	float y = 1.0 / (1.0 + exp(a / 2.0));
	float z = 1.0 / (1.0 + exp(b / 2.0));
	float w = 1.0 / (1.0 + exp(c / 2.0));
	float v = 1.0 / (1.0 + exp(d / 2.0));
 
	float4 C = B;
 
	D.r = (1.0 / (1.0 + exp(-a * (D.r - 0.5))) - y) / (1.0 - 2.0 * y);
	D.g = (1.0 / (1.0 + exp(-b * (D.g - 0.5))) - z) / (1.0 - 2.0 * z);
	D.b = (1.0 / (1.0 + exp(-c * (D.b - 0.5))) - w) / (1.0 - 2.0 * w);
 
	D = pow(abs(D), 1.0 / GEffectGamma);
 
	float4 Di = 1.0 - D;
 
	D = lerp(D, Di, GBleach);
 
	D.r = pow(abs(D.r), 1.0 / GEffectGammaR);
	D.g = pow(abs(D.g), 1.0 / GEffectGammaG);
	D.b = pow(abs(D.b), 1.0 / GEffectGammaB);
 
	if (D.r < 0.5)
		C.r = (2.0 * D.r - 1.0) * (B.r - B.r * B.r) + B.r;
	else
		C.r = (2.0 * D.r - 1.0) * (sqrt(B.r) - B.r) + B.r;
 
	if (D.g < 0.5)
		C.g = (2.0 * D.g - 1.0) * (B.g - B.g * B.g) + B.g;
	else
		C.g = (2.0 * D.g - 1.0) * (sqrt(B.g) - B.g) + B.g;
 	
	if (D.b < 0.5)
		C.b = (2.0 * D.b - 1.0) * (B.b - B.b * B.b) + B.b;
	else
		C.b = (2.0 * D.b - 1.0) * (sqrt(B.b) - B.b) + B.b;
 
	float4 F = lerp(B, C, GStrenght);
 
	F = (1.0 / (1.0 + exp(-d * (F - 0.5))) - v) / (1.0 - 2.0 * v);
 
	float r2R = 1.0 - GSaturation;
	float g2R = 0.0 + GSaturation;
	float b2R = 0.0 + GSaturation;
 
	float r2G = 0.0 + GSaturation;
	float g2G = (1.0 - GFade) - GSaturation;
	float b2G = (0.0 + GFade) + GSaturation;
 
	float r2B = 0.0 + Saturation;
	float g2B = (0.0 + GFade) + GSaturation;
	float b2B = (1.0 - GFade) - GSaturation;
 
	float4 iF = F;
 
	F.r = (iF.r * r2R + iF.g * g2R + iF.b * b2R);
	F.g = (iF.r * r2G + iF.g * g2G + iF.b * b2G);
	F.b = (iF.r * r2B + iF.g * g2B + iF.b * b2B);
 
	float N = GGetLuminance(F.rgb);
	float4 Cn = F;
 
	if (N < 0.5)
		Cn = (2.0 * N - 1.0) * (F - F * F) + F;
	else
		Cn = (2.0 * N - 1.0) * (sqrt(F) - F) + F;
 
	Cn = pow(abs(Cn), 1.0 / GLinearization);
 
	float4 Fn = lerp(B, Cn, GStrenght);

	//Fn = pow(Fn, 1/1.01);	

#define sharp_strength -3.0   
#define sharp_clamp    0.4  
#define pattern 3   
#define offset_bias 0.25                    
#define show_sharpen 0 
	#if (SSAO == 1)
	Fn = LumaSharpenPass(Fn,tex);	
	#endif
	float gdither_bit  = 8.0;      
     	float gseed = dot(tex, float2(12.9898,78.233)); 
     	float gsine = sin(gseed); 
    	float gnoise = frac(gsine * 43758.5453 + tex.x); 

     	float gdither_shift = (1.0 / (pow(2,gdither_bit) - 1.0)); 
	float gdither_shift_half = (gdither_shift * 0.5); 
     	gdither_shift = gdither_shift * gnoise - gdither_shift_half;  
     	Fn.rgb += float3(-gdither_shift, gdither_shift, -gdither_shift); 

	Fn = VibrancePass(Fn);

	Fn = pow(Fn, 1/1.08);
	return Fn;
}
