/*----------------------------.
  | :: Framework Initializer :: |
  '----------------------------*/
// Global Settings
#include "ReShade\PersonalFiles\KeyCodes.h"
#include "ReShade\Common.cfg"
#if RFX_Screenshot_Format != 2
	#pragma reshade screenshot_format bmp
#else
	#pragma reshade screenshot_format png
#endif
#if RFX_ShowFPS == 1
	#pragma reshade showfps
#endif
#if RFX_ShowClock == 1
	#pragma reshade showclock
#endif
#if RFX_ShowStatistics == 1
	#pragma reshade showstatistics
#endif
#if RFX_ShowToggleMessage == 1
	#pragma reshade showtogglemessage
#endif
// Global Variables
#define RFX_pixelSize RFX_PixelSize
#define RFX_PixelSize float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
#define RFX_ScreenSize float2(BUFFER_WIDTH, BUFFER_HEIGHT)
#define RFX_ScreenSizeFull float4(BUFFER_WIDTH, BUFFER_RCP_WIDTH, float(BUFFER_WIDTH) / float(BUFFER_HEIGHT), float(BUFFER_HEIGHT) / float(BUFFER_WIDTH)) // x = Width, y = 1 / Width, z = ScreenScaleY, w = 1 / ScreenScaleY
uniform float RFX_timer < string source = "timer"; >;
uniform float RFX_timeleft < string source = "timeleft"; >;
uniform float RFX_frametime < source = "frametime"; >;
// Global Textures and Samplers
texture RFX_depthBufferTex : DEPTH;
texture RFX_depthTex { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = R32F; };
texture RFX_backbufferTex : COLOR;
#if RFX_InitialStorage
	texture RFX_originalTex { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
#else
	texture RFX_originalTex : COLOR;
#endif
sampler RFX_depthColor { Texture = RFX_depthBufferTex; };
sampler RFX_depthTexColor { Texture = RFX_depthTex; };
sampler RFX_backbufferColor { Texture = RFX_backbufferTex; };
sampler RFX_originalColor { Texture = RFX_originalTex; };
// Fullscreen Triangle Vertex Shader
void RFX_VS_PostProcess(in uint id : SV_VertexID, out float4 pos : SV_Position, out float2 texcoord : TEXCOORD)
{
	texcoord.x = (id == 2) ? 2.0 : 0.0;
	texcoord.y = (id == 1) ? 2.0 : 0.0;
	pos = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
}
#if RFX_InitialStorage
float4 RFX_PS_StoreColor(float4 vpos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
	return tex2D(RFX_backbufferColor, texcoord);
}
#endif
#if RFX_DepthBufferCalc
float  RFX_PS_StoreDepth(in float4 position : SV_Position, in float2 texcoord : TEXCOORD0) : SV_Target
{
	float depth = tex2D(RFX_depthColor, texcoord).x;
	// Linearize depth	
#if RFX_LogDepth 
	depth = saturate(1.0f - depth);
	depth = (exp(pow(depth, 150 * pow(depth, 55) + 32.75f / pow(depth, 5) - 1850f * (pow((1 - depth), 2)))) - 1) / (exp(depth) - 1); // Made by LuciferHawk ;-)
#else
  	const float zFarPlane = RFX_Depth_z_far;
  	const float zNearPlane = RFX_Depth_z_near;
	depth = 1.0 / ((depth * ((zFarPlane - zNearPlane) / (-zFarPlane * zNearPlane)) + zFarPlane / (zFarPlane * zNearPlane)));
#endif
	// SweetFX Dither Method #1
	const float dither_bit = 8.0;
	float dither_shift = 0.25 * (1.0 / (pow(2, dither_bit) - 1.0));
	dither_shift = lerp(2.0 * dither_shift, -2.0 * dither_shift, frac(dot(texcoord, RFX_ScreenSize * float2(1.0 / 16.0, 10.0 / 36.0)) + 0.25));
	return depth + dither_shift;
}
#endif
#if RFX_InitialStorage || RFX_DepthBufferCalc
technique RFX_Setup_Tech < enabled = true; >
{
	#if RFX_InitialStorage
	pass StoreColor
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = RFX_PS_StoreColor;
		RenderTarget = RFX_originalTex;	
	}
	#endif
	#if RFX_DepthBufferCalc
	pass StoreDepth
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = RFX_PS_StoreDepth;
		RenderTarget = RFX_depthTex;
	}
	#endif
}
#endif
// Global Defines
#if defined(__RESHADE__) && __RESHADE__ >= 1700
	#define NAMESPACE_ENTER(name) namespace name {
	#define NAMESPACE_LEAVE() }
#else
	#define NAMESPACE_ENTER(name)
	#define NAMESPACE_LEAVE()
#endif
#define STR(name) #name
#define EFFECT(l,n) STR(ReShade/l/##n.h)
  /*----------------------------.
  | ::    Effect Pipeline    :: |
  '----------------------------*/
#include "ReShade\Pipeline.cfg"
  /*----------------------------.
  | ::  Framework Finalizer  :: |
  '----------------------------*/
#if RFX_ShowToggleMessage
float4 RFX_PS_ToggleMessage(in float4 position : SV_Position, in float2 texcoord : TEXCOORD0) : SV_Target
{
	return tex2D(RFX_backbufferColor, texcoord);
}
technique Framework < enabled = RFX_Start_Enabled; toggle = RFX_ToggleKey; >
{
	pass 
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = RFX_PS_ToggleMessage;
	}
}
#endif
#include "MasterEffect.h"
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// END OF TWEAKING VARIABLES      											     //
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//global vars
#define ScreenSize 	float4(BUFFER_WIDTH, BUFFER_RCP_WIDTH, float(BUFFER_WIDTH) / float(BUFFER_HEIGHT), float(BUFFER_HEIGHT) / float(BUFFER_WIDTH)) //x=Width, y=1/Width, z=ScreenScaleY, w=1/ScreenScaleY
#define PixelSize  	float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
#define PI 		3.1415972
#define PIOVER180 	0.017453292
#define AUTHOR 		MartyMcFly
#define FOV 		75
#define LumCoeff 	float3(0.212656, 0.715158, 0.072186)
#define zFarPlane 	1
#define zNearPlane 	0.001		//I know, weird values but ReShade's depthbuffer is ... odd
#define aspect          (BUFFER_RCP_HEIGHT/BUFFER_RCP_WIDTH)
#define InvFocalLen 	float2(tan(0.5f*radians(FOV)) / (float)BUFFER_RCP_HEIGHT * (float)BUFFER_RCP_WIDTH, tan(0.5f*radians(FOV)))
uniform float4 Timer < source = "timer"; >;
#pragma message "MasterEffect ReBorn 1.1.287 by Marty McFly"
#if( USE_HDR_LEVEL == 0)
 #define RENDERMODE RGBA8
#endif
#if( USE_HDR_LEVEL == 1)
 #define RENDERMODE RGBA16F
#endif
#if( USE_HDR_LEVEL == 2)
 #define RENDERMODE RGBA32F
#endif
//textures
texture   texBloom1 { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RENDERMODE;};
texture   texBloom2 { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RENDERMODE;};
texture   texBloom3 { Width = BUFFER_WIDTH/2; Height = BUFFER_HEIGHT/2; Format = RENDERMODE;};
texture   texBloom4 { Width = BUFFER_WIDTH/4; Height = BUFFER_HEIGHT/4; Format = RENDERMODE;};
texture   texBloom5 { Width = BUFFER_WIDTH/8; Height = BUFFER_HEIGHT/8; Format = RENDERMODE;};
texture   texLens1 { Width = BUFFER_WIDTH/2; Height = BUFFER_HEIGHT/2; Format = RENDERMODE;};
texture   texLens2 { Width = BUFFER_WIDTH/2; Height = BUFFER_HEIGHT/2; Format = RENDERMODE;};
texture2D texLDR : COLOR;
texture   texHDR1 	{ Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; MipLevels = 5; Format = RENDERMODE;};	
texture   texHDR2 	{ Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; MipLevels = 5; Format = RENDERMODE;};
texture   texOcclusion1 { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT;  Format = RGBA16F;}; //MUST be at least 16, 8 gives heavy artifacts when blurring.
texture   texOcclusion2 { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT;  Format = RGBA16F;}; //"Optimizations" can be done elsewhere, not here.
texture   texCoC	{ Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT;  MipLevels = 5; Format = RGBA16F;};
texture2D texDepth : DEPTH;
texture   texNoise  < string source = "MasterEffect/internal/mcnoise.png";  	> {Width = BUFFER_WIDTH;Height = BUFFER_HEIGHT;Format = RGBA8;};
texture   texSprite < string source = "MasterEffect/mcsprite.png"; 	 	> {Width = BUFFER_WIDTH;Height = BUFFER_HEIGHT;Format = RGBA8;};
texture   texDirt   < string source = "MasterEffect/mcdirt.png";   		> {Width = BUFFER_WIDTH;Height = BUFFER_HEIGHT;Format = RGBA8;};
texture   texLUT    < string source = "MasterEffect/mclut.png";    		> {Width = 256; Height = 1;   Format = RGBA8;};
texture   texLUT3D  < string source = "MasterEffect/mclut3d.png";  		> {Width = 256; Height = 16;   Format = RGBA8;};
texture   texMask   < string source = "MasterEffect/mcmask.png";   		> {Width = BUFFER_WIDTH;Height = BUFFER_HEIGHT;Format = R8;};
texture   texHeat   < string source = "MasterEffect/internal/mcheat.png";   	> {Width = 512;Height = 512;Format = RGBA8;};
//samplers
sampler SamplerBloom1 { Texture = texBloom1; };
sampler SamplerBloom2 { Texture = texBloom2; };
sampler SamplerBloom3 { Texture = texBloom3; };
sampler SamplerBloom4 { Texture = texBloom4; };
sampler SamplerBloom5 { Texture = texBloom5; };
sampler SamplerLens1 { Texture = texLens1; };
sampler SamplerLens2 { Texture = texLens2; };
sampler2D SamplerLDR
{
	Texture = texLDR;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU = Clamp;
	AddressV = Clamp;
};
sampler2D SamplerHDR1
{
	Texture = texHDR1;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU = Clamp;
	AddressV = Clamp;
};
sampler2D SamplerHDR2
{
	Texture = texHDR2;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU = Clamp;
	AddressV = Clamp;
};
sampler2D SamplerOcclusion1
{
	Texture = texOcclusion1;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU = Clamp;
	AddressV = Clamp;
};
sampler2D SamplerOcclusion2
{
	Texture = texOcclusion2;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU = Clamp;
	AddressV = Clamp;
};
sampler2D SamplerCoC
{
	Texture = texCoC;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU = Clamp;
	AddressV = Clamp;
};
sampler2D SamplerDepth
{
	Texture = texDepth;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU = Clamp;
	AddressV = Clamp;
};
sampler2D SamplerNoise
{
	Texture = texNoise;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU = Wrap;
	AddressV = Wrap;
};
sampler2D SamplerSprite
{
	Texture = texSprite;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU = Clamp;
	AddressV = Clamp;
};
sampler2D SamplerDirt
{
	Texture = texDirt;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU = Clamp;
	AddressV = Clamp;
};
sampler2D SamplerLUT
{
	Texture = texLUT;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU = Clamp;
	AddressV = Clamp;
};
sampler2D SamplerLUT3D
{
	Texture = texLUT3D;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU = Clamp;
	AddressV = Clamp;
};
sampler2D SamplerMask
{
	Texture = texMask;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU = Clamp;
	AddressV = Clamp;
};
sampler2D SamplerHeat
{
	Texture = texHeat;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU = Repeat;
	AddressV = Repeat;
};
struct VS_OUTPUT_POST
{
	float4 vpos : SV_Position;
	float2 txcoord : TEXCOORD0;
};
struct VS_INPUT_POST
{
	uint id : SV_VertexID;
};
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Vertex Shaders													     //
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
VS_OUTPUT_POST VS_MasterEffect(VS_INPUT_POST IN)
{
	VS_OUTPUT_POST OUT;
	OUT.txcoord.x = (IN.id == 2) ? 2.0 : 0.0;
	OUT.txcoord.y = (IN.id == 1) ? 2.0 : 0.0;
	OUT.vpos = float4(OUT.txcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
	return OUT;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// SMAA													     		     //
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "MasterEffect/internal/mcsmaa.hlsl"
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Functions														     //
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
float GetLinearDepth(float depth)
{
	return  1 / ((depth * ((zFarPlane - zNearPlane) / (-zFarPlane * zNearPlane)) + zFarPlane / (zFarPlane * zNearPlane)));
}
float3 GetNormalFromDepth(float fDepth, float2 vTexcoord) {
  
  	const float2 offset1 = float2(0.0,0.001);
  	const float2 offset2 = float2(0.001,0.0);
  
  	float depth1 = GetLinearDepth(tex2Dlod(SamplerDepth, float4(vTexcoord + offset1,0,0)).x);
  	float depth2 = GetLinearDepth(tex2Dlod(SamplerDepth, float4(vTexcoord + offset2,0,0)).x);
  
  	float3 p1 = float3(offset1, depth1 - fDepth);
  	float3 p2 = float3(offset2, depth2 - fDepth);
  
  	float3 normal = cross(p1, p2);
  	normal.z = -normal.z;
  
  	return normalize(normal);
}
float GetRandom(float2 co){
	return frac(sin(dot(co, float2(12.9898, 78.233))) * 43758.5453);
}
float3 GetRandomVector(float2 vTexCoord) {
  	return 2 * normalize(float3(GetRandom(vTexCoord - 0.5f),
				    GetRandom(vTexCoord + 0.5f),
				    GetRandom(vTexCoord))) - 1;
}
float4 GetAtlasTex(sampler tex, float2 coord, float spaltenzahl, float reihenzahl, float spalte, float reihe)
{
	return tex2Dlod(tex, float4(coord.xy/float2(spaltenzahl, reihenzahl)+float2((spalte-1)/spaltenzahl,(reihe-1)/reihenzahl),0,0));
}
float4 GaussBlur22(float2 coord, sampler tex, float mult, float lodlevel, bool isBlurVert) //texcoord, texture, blurmult in pixels, tex2dlod level, axis (0=horiz, 1=vert)
{
	float4 sum = 0;
	float2 axis = (isBlurVert) ? float2(0, 1) : float2(1, 0);
	float  weight[11] = {0.082607, 0.080977, 0.076276, 0.069041, 0.060049, 0.050187, 0.040306, 0.031105, 0.023066, 0.016436, 0.011254};
	for(int i=-10; i < 11; i++)
	{
		float currweight = weight[abs(i)];	
		sum	+= tex2Dlod(tex, float4(coord.xy + axis.xy * (float)i * PixelSize * mult,0,lodlevel)) * currweight;
	}
	return sum;
}
float4 GaussBlurGeneric(float2 coord, sampler tex, float mult, float lodlevel, bool isBlurVert, float Radius, float Quality) //texcoord, texture, blurmult in pixels, tex2dlod level, axis (0=horiz, 1=vert), offset count, quality
{
	float2 axis = (isBlurVert) ? float2(0, 1) : float2(1, 0);
	float4 Sigma = 0;
	
	Sigma.x				= 1.0f / ( sqrt( 2.0f * PI ) * Radius );
	Sigma.y				= exp( -0.5f / ( Radius * Radius ));
	Sigma.z				= Sigma.y * Sigma.y;
	Sigma.w				= Sigma.x;
	Sigma.xy			*= Sigma.yz;
	float4 sum = tex2Dlod(tex, float4(coord.xy,0,lodlevel))*Sigma.x;
	for(int i = 1; i < 150 && Sigma.w < Quality; i++) 
	{
		sum 	+= tex2Dlod(tex, float4(coord.xy + axis.xy * (float)i * PixelSize * mult,0,lodlevel)) * Sigma.x;
		sum 	+= tex2Dlod(tex, float4(coord.xy - axis.xy * (float)i * PixelSize * mult,0,lodlevel)) * Sigma.x;
		Sigma.w += 2.0 * Sigma.x;
		Sigma.xy *= Sigma.yz;
	}
	sum /= Sigma.w;
	return sum;
}
float smootherstep(float edge0, float edge1, float x)
{
   	x = clamp((x - edge0)/(edge1 - edge0), 0.0, 1.0);
   	return x*x*x*(x*(x*6 - 15) + 10);
}
float3 Hue(in float3 RGB)
{
   	// Based on work by Sam Hocevar and Emil Persson
   	float Epsilon = 1e-10;
   	float4 P = (RGB.g < RGB.b) ? float4(RGB.bg, -1.0, 2.0/3.0) : float4(RGB.gb, 0.0, -1.0/3.0);
   	float4 Q = (RGB.r < P.x) ? float4(P.xyw, RGB.r) : float4(RGB.r, P.yzx);
   	float C = Q.x - min(Q.w, Q.y);
   	float H = abs((Q.w - Q.y) / (6 * C + Epsilon) + Q.z);
   	return float3(H, C, Q.x);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Passes														     //
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
float4 BorderPass( float4 colorInput, float2 tex )
{
  	float3 fBorderColor_float = fBorderColor;
	float2 screen_size = float2(BUFFER_WIDTH, BUFFER_HEIGHT);
	float  screen_ratio = (BUFFER_WIDTH/BUFFER_HEIGHT);
  	float2 fBorderWidth_variable = fBorderWidth;
  	// -- calculate the right fBorderWidth for a given fBorderRatio --
  	//if (!any(fBorderWidth)) //if fBorderWidth is not used
  	if (fBorderWidth.x == -fBorderWidth.y) //if fBorderWidth is not used
    		if (screen_ratio < fBorderRatio)
      			fBorderWidth_variable = float2(0.0, (screen_size.y - (screen_size.x / fBorderRatio)) * 0.5);
    		else
      			fBorderWidth_variable = float2((screen_size.x - (screen_size.y * fBorderRatio)) * 0.5, 0.0);
  	float2 border = (PixelSize.xy * fBorderWidth_variable); //Translate integer pixel width to floating point
  	float2 within_border = saturate((-tex * tex + tex) - (-border * border + border)); //becomes positive when inside the border and 0 when outside
  	colorInput.rgb = all(within_border) ?  colorInput.rgb : fBorderColor_float ; //if the pixel is within the border use the original color, if not use the fBorderColor
  	return colorInput; //return the pixel
}
float3 CartoonPass( float3 colorInput, float2 tex, float2 pixelsize, sampler colorsampler )
{
 
  	float diff1 = dot(LumCoeff,tex2D(colorsampler, tex + pixelsize).rgb);
  	diff1 = dot(float4(LumCoeff,-1.0),float4(tex2D(colorsampler, tex - pixelsize).rgb , diff1));
  
  	float diff2 = dot(LumCoeff,tex2D(colorsampler, tex +float2(pixelsize.x,-pixelsize.y)).rgb);
  	diff2 = dot(float4(LumCoeff,-1.0),float4(tex2D(colorsampler, tex +float2(-pixelsize.x,pixelsize.y)).rgb , diff2));
    
  	float edge = dot(float2(diff1,diff2),float2(diff1,diff2));
  
  	colorInput.rgb =  pow(edge,CartoonEdgeSlope) * -CartoonPower + colorInput.rgb;
	
	return saturate(colorInput);
}
float3 LevelsPass( float3 colorInput )
{
	#define black_point_float ( Levels_black_point / 255.0 )
	#define white_point_float ( 255.0 / (Levels_white_point - Levels_black_point)) 
 	colorInput.rgb = colorInput.rgb * white_point_float - (black_point_float *  white_point_float);
  	return colorInput;
}
float3 TechniPass_prod80(float3 colorInput)
{
	float3 colStrength = float3(ColStrengthR,ColStrengthG,ColStrengthB);
	float3 tsource = saturate(colorInput.rgb);
	float3 ttemp = 1 - tsource;
	float3 ttarget = ttemp.grg;
	float3 ttarget2 = ttemp.bbr;
	float3 ttemp2 = tsource.rgb * ttarget.rgb;
	ttemp2.rgb *= ttarget2.rgb;
	ttemp.rgb = ttemp2.rgb * colStrength;
	ttemp2.rgb *= TechniBrightness;
	ttarget.rgb = ttemp.grg;
	ttarget2.rgb = ttemp.bbr;
	ttemp.rgb = tsource.rgb - ttarget.rgb;
	ttemp.rgb += ttemp2.rgb;
	ttemp2.rgb = ttemp.rgb - ttarget2.rgb;
	colorInput.rgb = lerp(tsource.rgb, ttemp2.rgb, TechniStrength);
	colorInput.rgb = lerp(dot(colorInput.rgb, 0.333), colorInput.rgb, TechniSat); 
	
	return colorInput.rgb;
}
float3 TechnicolorPass( float3 colorInput )
{
	#define cyanfilter float3(0.0, 1.30, 1.0)
	#define magentafilter float3(1.0, 0.0, 1.05) 
	#define yellowfilter float3(1.6, 1.6, 0.05)
	#define redorangefilter float2(1.05, 0.620) //RG_
	#define greenfilter float2(0.30, 1.0)       //RG_
	#define magentafilter2 magentafilter.rb     //R_B
	float3 tcol = colorInput.rgb;
	
  	float2 rednegative_mul   = tcol.rg * (1.0 / (redNegativeAmount * TechniPower));
	float2 greennegative_mul = tcol.rg * (1.0 / (greenNegativeAmount * TechniPower));
	float2 bluenegative_mul  = tcol.rb * (1.0 / (blueNegativeAmount * TechniPower));
	
  	float rednegative   = dot( redorangefilter, rednegative_mul );
	float greennegative = dot( greenfilter, greennegative_mul );
	float bluenegative  = dot( magentafilter2, bluenegative_mul );
	
	float3 redoutput   = rednegative.rrr + cyanfilter;
	float3 greenoutput = greennegative.rrr + magentafilter;
	float3 blueoutput  = bluenegative.rrr + yellowfilter;
	
	float3 result = redoutput * greenoutput * blueoutput;
	colorInput.rgb = lerp(tcol, result, TechniAmount);
	return colorInput;
}
float3 DPXPass(float3 InputColor){
	float3x3 RGB =
	float3x3(
	2.67147117265996,-1.26723605786241,-0.410995602172227,
	-1.02510702934664,1.98409116241089,0.0439502493584124,
	0.0610009456429445,-0.223670750812863,1.15902104167061
	);
	float3x3 XYZ =
	float3x3(
	0.500303383543316,0.338097573222739,0.164589779545857,
	0.257968894274758,0.676195259144706,0.0658358459823868,
	0.0234517888692628,0.1126992737203,0.866839673124201
	);
	float DPXContrast = 0.1;
	float DPXGamma = 1.0;
	float RedCurve = DPXRed;
	float GreenCurve = DPXGreen;
	float BlueCurve = DPXBlue;
	
	float3 RGB_Curve = float3(DPXRed,DPXGreen,DPXBlue);
	float3 RGB_C = float3(DPXRedC,DPXGreenC,DPXBlueC);
	float3 B = InputColor.rgb;
	B = pow(B, 1.0/DPXGamma);
 	B = B * (1.0 - DPXContrast) + (0.5 * DPXContrast);
	float3 Btemp = (1.0 / (1.0 + exp(RGB_Curve / 2.0)));	  
	B = ((1.0 / (1.0 + exp(-RGB_Curve * (B - RGB_C)))) / (-2.0 * Btemp + 1.0)) + (-Btemp / (-2.0 * Btemp + 1.0));
    	float value = max(max(B.r, B.g), B.b);
	float3 color = B / value;
	color = saturate(color);
	color = pow(color, 1.0/DPXColorGamma);
	
	float3 c0 = color * value;
        c0 = mul(XYZ, c0);
	float luma = dot(c0, float3(0.30, 0.59, 0.11)); //Use BT 709 instead?
        c0 = (1.0 - DPXSaturation) * luma + DPXSaturation * c0;
	c0 = mul(RGB, c0);
	
	InputColor.rgb = lerp(InputColor.rgb, c0, DPXBlend);
	return InputColor;
}
float3 LiftGammaGainPass( float3 colorInput )
{
	// -- Get input --
	float3 color = colorInput.rgb;
	
	// -- Lift --
	color = color * (1.5-0.5 * RGB_Lift) + 0.5 * RGB_Lift - 0.5;
	color = saturate(color); //isn't strictly necessary, but doesn't cost performance.
	
	// -- Gain --
	color *= RGB_Gain; 
	
	// -- Gamma --
	colorInput.rgb = pow(color, 1.0 / RGB_Gamma); //Gamma
	
	// -- Return output --
	//return (colorInput);
	return saturate(colorInput);
}
float3 TonemapPass( float3 colorInput )
{
	float3 color = colorInput.rgb;
	color = saturate(color - Defog * FogColor); // Defog
	
	color *= pow(2.0f, Exposure); // Exposure
	
	color = pow(color, Gamma);    // Gamma -- roll into the first gamma correction in main.h ?
	
	float lum = dot(LumCoeff, color.rgb);
	
	float3 blend = lum.rrr; //dont use float3
	
	float L = saturate( 10.0 * (lum - 0.45) );
  	
	float3 result1 = 2.0f * color.rgb * blend;
	float3 result2 = 1.0f - 2.0f * (1.0f - blend) * (1.0f - color.rgb);
	
	float3 newColor = lerp(result1, result2, L);
	float3 A2 = Bleach * color.rgb; //why use a float for A2 here and then multiply by color.rgb (a float3)?
	float3 mixRGB = A2 * newColor;
	
	color.rgb += ((1.0f - A2) * mixRGB);
	
	float3 middlegray = dot(color,(1.0/3.0)); //1fps slower than the original on nvidia, 2 fps faster on AMD
	
	float3 diffcolor = color - middlegray; //float 3 here
	colorInput.rgb = (color + diffcolor * Saturation)/(1+(diffcolor*Saturation)); //saturation
	
	return colorInput;
}
float3 VibrancePass( float3 colorInput )
{
   	#define Vibrance_coeff float3(Vibrance_RGB_balance * Vibrance)
	float3 color = colorInput; //original input color
  	float3 lumCoeff = float3(0.212656, 0.715158, 0.072186);  //Values to calculate luma with
	float luma = dot(LumCoeff, color.rgb); //calculate luma (grey)
	float max_color = max(colorInput.r, max(colorInput.g,colorInput.b)); //Find the strongest color
	float min_color = min(colorInput.r, min(colorInput.g,colorInput.b)); //Find the weakest color
  	float color_saturation = max_color - min_color; //The difference between the two is the saturation
   	color.rgb = lerp(luma, color.rgb, (1.0 + (Vibrance_coeff * (1.0 - (sign(Vibrance_coeff) * color_saturation))))); //extrapolate between luma and original by 1 + (1-saturation) - current
 	return color; //return the result
}
float3 CurvesPass( float3 colorInput )
{
  float Curves_contrast_blend = Curves_contrast;
   /*-----------------------------------------------------------.
  /               Separation of Luma and Chroma                 /
  '-----------------------------------------------------------*/
  	// -- Calculate Luma and Chroma if needed --
  	#if Curves_mode != 2
    	//calculate luma (grey)
    	float luma = dot(LumCoeff, colorInput.rgb);
    	//calculate chroma
	float3 chroma = colorInput.rgb - luma;
  	#endif
  	// -- Which value to put through the contrast formula? --
  	// I name it x because makes it easier to copy-paste to Graphtoy or Wolfram Alpha or another graphing program
  	#if Curves_mode == 2
	float3 x = colorInput.rgb; //if the curve should be applied to both Luma and Chroma
	#elif Curves_mode == 1
	float3 x = chroma; //if the curve should be applied to Chroma
	x = x * 0.5 + 0.5; //adjust range of Chroma from -1 -> 1 to 0 -> 1
  	#else // Curves_mode == 0
    	float x = luma; //if the curve should be applied to Luma
  	#endif
   /*-----------------------------------------------------------.
  /                     Contrast formulas                       /
  '-----------------------------------------------------------*/
  	// -- Curve 1 --
  	#if Curves_formula == 1
    	x = sin(PI * 0.5 * x); // Sin - 721 amd fps, +vign 536 nv
    	x *= x;
    
    	//x = 0.5 - 0.5*cos(PI*x);
    	//x = 0.5 * -sin(PI * -x + (PI*0.5)) + 0.5;
  	#endif
  	// -- Curve 2 --
  	#if Curves_formula == 2
    	x = x - 0.5;  
    	x = ( x / (0.5 + abs(x)) ) + 0.5;
    
    	//x = ( (x - 0.5) / (0.5 + abs(x-0.5)) ) + 0.5;
  	#endif
  	// -- Curve 3 --
  	#if Curves_formula == 3
    	//x = smoothstep(0.0,1.0,x); //smoothstep
    	x = x*x*(3.0-2.0*x); //faster smoothstep alternative - 776 amd fps, +vign 536 nv
    	//x = x - 2.0 * (x - 1.0) * x* (x- 0.5);  //2.0 is contrast. Range is 0.0 to 2.0
  	#endif
  	// -- Curve 4 --
  	#if Curves_formula == 4
    	x = (1.0524 * exp(6.0 * x) - 1.05248) / (20.0855 + exp(6.0 * x)); //exp formula
  	#endif
  	// -- Curve 5 --
  	#if Curves_formula == 5
    	//x = 0.5 * (x + 3.0 * x * x - 2.0 * x * x * x); //a simplified catmull-rom (0,0,1,1) - btw smoothstep can also be expressed as a simplified catmull-rom using (1,0,1,0)
    	//x = (0.5 * x) + (1.5 -x) * x*x; //estrin form - faster version
    	x = x * (x * (1.5-x) + 0.5); //horner form - fastest version
    	Curves_contrast_blend = Curves_contrast * 2.0; //I multiply by two to give it a strength closer to the other curves.
  	#endif
 	// -- Curve 6 --
  	#if Curves_formula == 6
    	x = x*x*x*(x*(x*6.0 - 15.0) + 10.0); //Perlins smootherstep
  	#endif
	// -- Curve 7 --
  	#if Curves_formula == 7
    	//x = ((x-0.5) / ((0.5/(4.0/3.0)) + abs((x-0.5)*1.25))) + 0.5;
	x = x - 0.5;
	x = x / ((abs(x)*1.25) + 0.375 ) + 0.5;
	//x = ( (x-0.5) / ((abs(x-0.5)*1.25) + (0.5/(4.0/3.0))) ) + 0.5;
  	#endif
  	// -- Curve 8 --
  	#if Curves_formula == 8
    	x = (x * (x * (x * (x * (x * (x * (1.6 * x - 7.2) + 10.8) - 4.2) - 3.6) + 2.7) - 1.8) + 2.7) * x * x; //Techicolor Cinestyle - almost identical to curve 1
  	#endif
  	// -- Curve 9 --
  	#if Curves_formula == 9
    	x =  -0.5 * (x*2.0-1.0) * (abs(x*2.0-1.0)-2.0) + 0.5; //parabola
  	#endif
  	// -- Curve 10 --
  	#if Curves_formula == 10 //Half-circles
    	#if Curves_mode == 0
      	float xstep = step(x,0.5);
	float xstep_shift = (xstep - 0.5);
	float shifted_x = x + xstep_shift;
   	#else
      	float3 xstep = step(x,0.5);
	float3 xstep_shift = (xstep - 0.5);
	float3 shifted_x = x + xstep_shift;
    	#endif
	x = abs(xstep - sqrt(-shifted_x * shifted_x + shifted_x) ) - xstep_shift;
  	//x = abs(step(x,0.5)-sqrt(-(x+step(x,0.5)-0.5)*(x+step(x,0.5)-0.5)+(x+step(x,0.5)-0.5)))-(step(x,0.5)-0.5); //single line version of the above
    
  	//x = 0.5 + (sign(x-0.5)) * sqrt(0.25-(x-trunc(x*2))*(x-trunc(x*2))); //worse
  
  	/* // if/else - even worse
  	if (x-0.5)
  	x = 0.5-sqrt(0.25-x*x);
  	else
  	x = 0.5+sqrt(0.25-(x-1)*(x-1));
	*/
  	//x = (abs(step(0.5,x)-clamp( 1-sqrt(1-abs(step(0.5,x)- frac(x*2%1)) * abs(step(0.5,x)- frac(x*2%1))),0 ,1))+ step(0.5,x) )*0.5; //worst so far
	
	//TODO: Check if I could use an abs split instead of step. It might be more efficient
	
	Curves_contrast_blend = Curves_contrast * 0.5; //I divide by two to give it a strength closer to the other curves.
  	#endif
  	// -- Curve 11 --
  	#if Curves_formula == 11 //Cubic catmull
    	float a = 1.00; //control point 1
    	float b = 0.00; //start point
    	float c = 1.00; //endpoint
    	float d = 0.20; //control point 2
    	x = 0.5 * ((-a + 3*b -3*c + d)*x*x*x + (2*a -5*b + 4*c - d)*x*x + (-a+c)*x + 2*b); //A customizable cubic catmull-rom spline
  	#endif
  	// -- Curve 12 --
  	#if Curves_formula == 12 //Cubic Bezier spline
    	float a = 0.00; //start point
    	float b = 0.00; //control point 1
    	float c = 1.00; //control point 2
    	float d = 1.00; //endpoint
    	float r  = (1-x);
	float r2 = r*r;
	float r3 = r2 * r;
	float x2 = x*x;
	float x3 = x2*x;
	//x = dot(float4(a,b,c,d),float4(r3,3*r2*x,3*r*x2,x3));
	//x = a * r*r*r + r * (3 * b * r * x + 3 * c * x*x) + d * x*x*x;
	//x = a*(1-x)*(1-x)*(1-x) +(1-x) * (3*b * (1-x) * x + 3 * c * x*x) + d * x*x*x;
	x = a*(1-x)*(1-x)*(1-x) + 3*b*(1-x)*(1-x)*x + 3*c*(1-x)*x*x + d*x*x*x;
  	#endif
  	// -- Curve 13 --
  	#if Curves_formula == 13 //Cubic Bezier spline - alternative implementation.
    	float3 a = float3(0.00,0.00,0.00); //start point
    	float3 b = float3(0.25,0.15,0.85); //control point 1
    	float3 c = float3(0.75,0.85,0.15); //control point 2
    	float3 d = float3(1.00,1.00,1.00); //endpoint
    	float3 ab = lerp(a,b,x);           // point between a and b
    	float3 bc = lerp(b,c,x);           // point between b and c
    	float3 cd = lerp(c,d,x);           // point between c and d
    	float3 abbc = lerp(ab,bc,x);       // point between ab and bc
    	float3 bccd = lerp(bc,cd,x);       // point between bc and cd
    	float3 dest = lerp(abbc,bccd,x);   // point on the bezier-curve
    	x = dest;
  	#endif
  	// -- Curve 14 --
  	#if Curves_formula == 14
    	x = 1.0 / (1.0 + exp(-(x * 10.0 - 5.0))); //alternative exp formula
  	#endif
   /*-----------------------------------------------------------.
  /                 Joining of Luma and Chroma                  /
  '-----------------------------------------------------------*/
  	#if Curves_mode == 2 //Both Luma and Chroma
	float3 color = x;  //if the curve should be applied to both Luma and Chroma
	colorInput.rgb = lerp(colorInput.rgb, color, Curves_contrast_blend); //Blend by Curves_contrast
  	#elif Curves_mode == 1 //Only Chroma
	x = x * 2.0 - 1.0; //adjust the Chroma range back to -1 -> 1
	float3 color = luma + x; //Luma + Chroma
	colorInput.rgb = lerp(colorInput.rgb, color, Curves_contrast_blend); //Blend by Curves_contrast
  	#else // Curves_mode == 0 //Only Luma
    	x = lerp(luma, x, Curves_contrast_blend); //Blend by Curves_contrast
    	colorInput.rgb = x + chroma; //Luma + Chroma
  	#endif
  	//Return the result
  	return colorInput;
}
float3 SepiaPass( float3 colorInput )
{
	float3 sepia = colorInput.rgb;
	
	// calculating amounts of input, grey and sepia colors to blend and combine
	float grey = dot(sepia, LumCoeff);
	sepia *= ColorTone;
	
	float3 blend2 = (grey * GreyPower) + (colorInput.rgb / (GreyPower + 1));
	colorInput.rgb = lerp(blend2, sepia, SepiaPower);
	// returning the final color
	return colorInput;
}
float3 SkyrimTonemapPass( float3 color )
{
	float	grayadaptation = dot(color.xyz, LumCoeff);
	#if (POSTPROCESS==1)
	color.xyz =  color.xyz / (grayadaptation * EAdaptationMaxV1 + EAdaptationMinV1);
	float cgray = dot( color.xyz, LumCoeff);
	cgray = pow(cgray, EContrastV1);
	float3 poweredcolor = pow( abs(color.xyz), EColorSaturationV1);
	float newgray = dot(poweredcolor.xyz, LumCoeff);
	color.xyz = poweredcolor.xyz * cgray / (newgray + 0.0001);
	float3	luma =  color.xyz;
	float	lumamax = 300.0;
	color.xyz = ( color.xyz * (1.0 +  color.xyz / lumamax)) / ( color.xyz + EToneMappingCurveV1);	
	#endif
	#if (POSTPROCESS==2)
	color.xyz =  color.xyz / (grayadaptation * EAdaptationMaxV2 + EAdaptationMinV2);
	float3 xncol = normalize( color.xyz);
	float3 scl =  color.xyz / xncol.xyz;
	scl = pow(scl, EIntensityContrastV2);
	xncol.xyz = pow(xncol.xyz, EColorSaturationV2);
	color.xyz = scl*xncol.xyz;
	float	lumamax = EToneMappingOversaturationV2;
	color.xyz = ( color.xyz * (1.0 +  color.xyz / lumamax)) / ( color.xyz + EToneMappingCurveV2);
 	color.xyz*=4;
	#endif
	#if (POSTPROCESS==3)
	color.xyz *= 35;
	float	lumamax = EToneMappingOversaturationV3;
	color.xyz = ( color.xyz * (1.0 +  color.xyz / lumamax)) / ( color.xyz + EToneMappingCurveV3);
	#endif
	#if (POSTPROCESS == 4)
	color.xyz =  color.xyz / (grayadaptation * EAdaptationMaxV4 + EAdaptationMinV4);
	float Y = dot( color.xyz, float3(0.299, 0.587, 0.114)); //0.299 * R + 0.587 * G + 0.114 * B;
	float U = dot( color.xyz, float3(-0.14713, -0.28886, 0.436)); //-0.14713 * R - 0.28886 * G + 0.436 * B;
	float V = dot( color.xyz, float3(0.615, -0.51499, -0.10001)); //0.615 * R - 0.51499 * G - 0.10001 * B;
	Y = pow(Y, EBrightnessCurveV4);
	Y = Y * EBrightnessMultiplierV4;
	color.xyz = V * float3(1.13983, -0.58060, 0.0) + U * float3(0.0, -0.39465, 2.03211) + Y;
	color.xyz = max( color.xyz, 0.0);
	color.xyz =  color.xyz / ( color.xyz + EBrightnessToneMappingCurveV4);
	#endif
	#if (POSTPROCESS == 5)
	float hnd = 1;
	float2 hndtweak = float2( 3.1 , 1.5 );
        color.xyz *= lerp( hndtweak.x, hndtweak.y, hnd );
	float3 xncol = normalize( color.xyz);
	float3 scl =  color.xyz/xncol.xyz;
	scl = pow(scl, EIntensityContrastV5);
	xncol.xyz = pow(xncol.xyz, EColorSaturationV5);
	color.xyz = scl*xncol.xyz;
	color.xyz *= HCompensateSatV5; // compensate for darkening caused my EcolorSat above
	color.xyz =  color.xyz / ( color.xyz + EToneMappingCurveV5);
	color.xyz *= 4;
	#endif
	#if (POSTPROCESS==6)
	//Postprocessing V6 by Kermles
	//tuned by the master himself for ME 1.4, thanks man!!!
	//hd6/ppv2///////////////////////////////////////////
	float 	EIntensityContrastV6 = EIntensityContrastV6Day;
	float 	EColorSaturationV6 = EColorSaturationV6Day;
	float 	HCompensateSatV6 = HCompensateSatV6Day;
	float 	EToneMappingCurveV6 = EToneMappingCurveV6Day;
	float 	EBrightnessV6 = EBrightnessV6Day;
	float 	EToneMappingOversaturationV6 = EToneMappingOversaturationV6Day;
	float 	EAdaptationMaxV6 = EAdaptationMaxV6Day;
	float 	EAdaptationMinV6 = EAdaptationMinV6Day;
	float	lumamax = EToneMappingOversaturationV6;
	//kermles////////////////////////////////////////////
	float4 	ncolor;					//temporary variable for color adjustments		
	//begin pp code/////////////////////////////////////////////////
	//ppv2 modified by kermles//////////////////////////////////////
		
	grayadaptation = clamp(grayadaptation, 0, 50);
	color.xyz *= EBrightnessV6;
	float3 xncol = normalize( color.xyz);
	float3 scl =  color.xyz/xncol.xyz;
	scl = pow(saturate(scl), EIntensityContrastV6);
	xncol.xyz = pow(xncol.xyz, EColorSaturationV6);
	color.xyz = scl*xncol.xyz;
	color.xyz *= HCompensateSatV6;
	color.xyz = ( color.xyz * (1.0 +  color.xyz/lumamax))/( color.xyz + EToneMappingCurveV6);
	color.xyz /= grayadaptation*EAdaptationMaxV6+EAdaptationMinV6;
	//rerun ppv2////////////////////////////////////////////////////
	color.xyz *= EBrightnessV6;
	xncol = normalize( color.xyz);
	scl =  color.xyz/xncol.xyz;
	scl = saturate(scl);
	scl = pow(scl, EIntensityContrastV6);
	xncol.xyz = pow(xncol.xyz, EColorSaturationV6);
	color.xyz = scl*xncol.xyz;
	color.xyz *= HCompensateSatV6;
	color.xyz = ( color.xyz * (1.0 +  color.xyz/lumamax))/( color.xyz + EToneMappingCurveV6);
	#endif
	return color;
}
float3 MoodPass( float3 colorInput )
{
	float3 colInput = colorInput;
	float3 colMood = 1.0f;
	colMood.r = moodR;
	colMood.g = moodG;
	colMood.b = moodB;
	float fLum = ( colInput.r + colInput.g + colInput.b ) / 3;
	colMood = lerp(0, colMood, saturate(fLum * 2.0));
	colMood = lerp(colMood, 1, saturate(fLum - 0.5) * 2.0);
	float3 colOutput = lerp(colInput, colMood, saturate(fLum * fRatio));
	colorInput=max(0, colOutput);
	return colorInput;
}
float3 CrossPass(float3 color)
{
	float2 CrossMatrix [3] = {
		float2 (1.03, 0.04),
		float2 (1.09, 0.01),
		float2 (0.78, 0.13),
 		};
	float3 image1 = color;
	float3 image2 = color;
	float gray = dot(float3(0.5,0.5,0.5), image1);  
	image1 = lerp (gray, image1,CrossSaturation);
	image1 = lerp (0.35, image1,CrossContrast);
	image1 +=CrossBrightness;
	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;
	color = lerp(image1, image2, CrossAmount);
	return color;
}
float3 FilmPass(float3 B)
{
	float3 G = B;
	float3 H = 0.01;
 
	B = saturate(B);
	B = pow(B, Linearization);
	B = lerp(H, B, Contrast);
 
	float A = dot(B.rgb, LumCoeff);
	float3 D = A;
 
	B = pow(B, 1.0 / BaseGamma);
 
	float a = FRedCurve;
	float b = FGreenCurve;
	float c = FBlueCurve;
	float d = BaseCurve;
 
	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));
 
	float3 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(D, 1.0 / EffectGamma);
 
	float3 Di = 1.0 - D;
 
	D = lerp(D, Di, FBleach);
 
	D.r = pow(abs(D.r), 1.0 / EffectGammaR);
	D.g = pow(abs(D.g), 1.0 / EffectGammaG);
	D.b = pow(abs(D.b), 1.0 / EffectGammaB);
 
	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 (AgainstAllAutority) 
	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;
 
	float3 F = lerp(B, C, Strenght);
 
	F = (1.0 / (1.0 + exp(-d * (F - 0.5))) - v) / (1.0 - 2.0 * v);
 
	float r2R = 1.0 - FSaturation;
	float g2R = 0.0 + FSaturation;
	float b2R = 0.0 + FSaturation;
 
	float r2G = 0.0 + FSaturation;
	float g2G = (1.0 - Fade) - FSaturation;
	float b2G = (0.0 + Fade) + FSaturation;
 
	float r2B = 0.0 + FSaturation;
	float g2B = (0.0 + Fade) + FSaturation;
	float b2B = (1.0 - Fade) - FSaturation;
 
	float3 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 = dot(F.rgb, LumCoeff);
	float3 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(max(Cn,0), 1.0 / Linearization);
 
	float3 Fn = lerp(B, Cn, Strenght);
	return Fn;
}
float3 ReinhardToneMapping(in float3 x)
{
	const float W =  ReinhardWhitepoint;	// Linear White Point Value
    	const float K =  ReinhardScale;        // Scale
    	// gamma space or not?
    	return (1 + K * x / (W * W)) * x / (x + K);
}
float3 ReinhardLinearToneMapping(in float3 x)
{
    	const float W = ReinhardLinearWhitepoint;	        // Linear White Point Value
    	const float L = ReinhardLinearPoint;           // Linear point
    	const float C = ReinhardLinearSlope;           // Slope of the linear section
    	const float K = (1 - L * C) / C; // Scale (fixed so that the derivatives of the Reinhard and linear functions are the same at x = L)
    	float3 reinhard = L * C + (1 - L * C) * (1 + K * (x - L) / ((W - L) * (W - L))) * (x - L) / (x - L + K);
    	// gamma space or not?
    	return (x > L) ? reinhard : C * x;
}
float3 HaarmPeterDuikerFilmicToneMapping(in float3 x)
{
    	x = max( (float3)0.0f, x - 0.004f );
    	return pow( abs( ( x * ( 6.2f * x + 0.5f ) ) / ( x * ( 6.2f * x + 1.7f ) + 0.06 ) ), 2.2f );
}
float3 CustomToneMapping(in float3 x)
{
	const float A = 0.665f;
	const float B = 0.09f;
	const float C = 0.004f;
	const float D = 0.445f;
	const float E = 0.26f;
	const float F = 0.025f;
	const float G = 0.16f;//0.145f;
	const float H = 1.1844f;//1.15f;
    // gamma space or not?
	return (((x*(A*x+B)+C)/(x*(D*x+E)+F))-G) / H;
}
float3 ColorFilmicToneMapping(in float3 x)
{
	// Filmic tone mapping
	const float3 A = float3(0.55f, 0.50f, 0.45f);	// Shoulder strength
	const float3 B = float3(0.30f, 0.27f, 0.22f);	// Linear strength
	const float3 C = float3(0.10f, 0.10f, 0.10f);	// Linear angle
	const float3 D = float3(0.10f, 0.07f, 0.03f);	// Toe strength
	const float3 E = float3(0.01f, 0.01f, 0.01f);	// Toe Numerator
	const float3 F = float3(0.30f, 0.30f, 0.30f);	// Toe Denominator
	const float3 W = float3(2.80f, 2.90f, 3.10f);	// Linear White Point Value
	const float3 F_linearWhite = ((W*(A*W+C*B)+D*E)/(W*(A*W+B)+D*F))-(E/F);
	float3 F_linearColor = ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-(E/F);
    // gamma space or not?
	return pow(saturate(F_linearColor * 1.25 / F_linearWhite),1.25);
}
float3 ColormodPass( float3 color )
{
	color.xyz = (color.xyz - dot(color.xyz, 0.333)) * ColormodChroma + dot(color.xyz, 0.333);
	color.xyz = saturate(color.xyz);
	color.x = (pow(color.x, ColormodGammaR) - 0.5) * ColormodContrastR + 0.5 + ColormodBrightnessR;
	color.y = (pow(color.y, ColormodGammaG) - 0.5) * ColormodContrastG + 0.5 + ColormodBrightnessB;
	color.z = (pow(color.z, ColormodGammaB) - 0.5) * ColormodContrastB + 0.5 + ColormodBrightnessB;
	return color;	
}
float3 SphericalPass( float3 color )
{
	float3 signedColor = color.rgb * 2.0 - 1.0;
	float3 sphericalColor = sqrt(1.0 - signedColor.rgb * signedColor.rgb);
	sphericalColor = sphericalColor * 0.5 + 0.5;
	sphericalColor *= color.rgb;
	color.rgb += sphericalColor.rgb * sphericalAmount;
	color.rgb *= 0.95;
	return color;
}
float3 SincityPass(float3 color)
{
	float sinlumi = dot(color.rgb, float3(0.30f,0.59f,0.11f));
	if(color.r > (color.g + 0.2f) && color.r > (color.b + 0.025f))
	{
		color.rgb = float3(sinlumi, 0, 0)*1.5;
	}
	else
	{
		color.rgb = sinlumi;
	}
	return color;
}
float3 colorhuefx_prod80( float3 color )
{
	
	float3 fxcolor = saturate( color.xyz );
	float greyVal = dot( fxcolor.xyz, LumCoeff.xyz );
	float3 HueSat = Hue( fxcolor.xyz );
	float colorHue = HueSat.x;
	float colorInt = HueSat.z - HueSat.y * 0.5;
	float colorSat = HueSat.y / ( 1.0 - abs( colorInt * 2.0 - 1.0 ) * 1e-10 );
	//When color intensity not based on original saturation level
   	if ( USE_COLORSAT == 0 )   colorSat = 1.0f;
	float hueMin_1 = hueMid - hueRange;
	float hueMax_1 = hueMid + hueRange;
	float hueMin_2 = 0.0f;
	float hueMax_2 = 0.0f;
   	if ( hueMin_1 < 0.0 )
   	{
   		hueMin_2 = 1.0f + hueMin_1;
   		hueMax_2 = 1.0f + hueMid;
   
      		if ( colorHue >= hueMin_1 && colorHue <= hueMid )
         		fxcolor.xyz = lerp( greyVal.xxx, fxcolor.xyz, smootherstep( hueMin_1, hueMid, colorHue ) * ( colorSat * satLimit ));
      		else if ( colorHue >= hueMid && colorHue <= hueMax_1 )
        		fxcolor.xyz = lerp( greyVal.xxx, fxcolor.xyz, ( 1.0f - smootherstep( hueMid, hueMax_1, colorHue )) * ( colorSat * satLimit ));
      		else if ( colorHue >= hueMin_2 && colorHue <= hueMax_2 )
         		fxcolor.xyz = lerp( greyVal.xxx, fxcolor.xyz, smootherstep( hueMin_2, hueMax_2, colorHue ) * ( colorSat * satLimit ));
      		else
         		fxcolor.xyz = greyVal.xxx;
   	}
   	else if ( hueMax_1 > 1.0 )
   	{
   		hueMin_2 = 0.0f - ( 1.0f - hueMid );
   		hueMax_2 = hueMax_1 - 1.0f;
      		if ( colorHue >= hueMin_1 && colorHue <= hueMid )
         		fxcolor.xyz = lerp( greyVal.xxx, fxcolor.xyz, smootherstep( hueMin_1, hueMid, colorHue ) * ( colorSat * satLimit ));
      		else if ( colorHue >= hueMid && colorHue <= hueMax_1 )
         		fxcolor.xyz = lerp( greyVal.xxx, fxcolor.xyz, ( 1.0f - smootherstep( hueMid, hueMax_1, colorHue )) * ( colorSat * satLimit ));
      		else if ( colorHue >= hueMin_2 && colorHue <= hueMax_2 )
         		fxcolor.xyz = lerp( greyVal.xxx, fxcolor.xyz, ( 1.0f - smootherstep( hueMin_2, hueMax_2, colorHue )) * ( colorSat * satLimit ));
      		else
         		fxcolor.xyz = greyVal.xxx;
   	}	
   
	else
   	{
      		if ( colorHue >= hueMin_1 && colorHue <= hueMid )
        		fxcolor.xyz = lerp( greyVal.xxx, fxcolor.xyz, smootherstep( hueMin_1, hueMid, colorHue ) * ( colorSat * satLimit ));
      		else if ( colorHue > hueMid && colorHue <= hueMax_1 )
         		fxcolor.xyz = lerp( greyVal.xxx, fxcolor.xyz, ( 1.0f - smootherstep( hueMid, hueMax_1, colorHue )) * ( colorSat * satLimit ));
      		else
         		fxcolor.xyz = greyVal.xxx;
   	}
   	color.xyz = lerp( color.xyz, fxcolor.xyz, fxcolorMix );
	return color.xyz;
}
float3 SharpPass( float3 colorInput, float2 tex, sampler colorsampler)
{
     	float3 blur_ori = tex2D(colorsampler, tex + float2(0.5 * PixelSize.x,-PixelSize.y * fSharpBias)).rgb*0.25;  	// South South East
    	blur_ori += tex2D(colorsampler, tex + float2(fSharpBias * -PixelSize.x,0.5 * -PixelSize.y)).rgb*0.25; 		// West South West
   	blur_ori += tex2D(colorsampler, tex + float2(fSharpBias * PixelSize.x,0.5 * PixelSize.y)).rgb*0.25; 		// East North East
    	blur_ori += tex2D(colorsampler, tex + float2(0.5 * -PixelSize.x,PixelSize.y * fSharpBias)).rgb*0.25;		// North North West
	float3 sharp = colorInput - blur_ori;
	float sharp_luma = dot(sharp, fSharpStrength);
	
	sharp_luma = clamp(sharp_luma, -fSharpClamp, fSharpClamp);
	
	float3 done = tex2D(colorsampler, tex).rgb + sharp_luma; 
	colorInput = done;
	return colorInput;
}
float3 ExplosionPass( float3 colorInput, float2 tex, sampler colorsampler )
{
  	// -- pseudo random number generator --
  	float2 sine_cosine;
  	sincos(dot(tex, float2(12.9898,78.233)),sine_cosine.x,sine_cosine.y);
  	sine_cosine = sine_cosine * 43758.5453 + tex;
  	float2 noise = frac(sine_cosine);
  	tex = (-fExplosionRadius * PixelSize) + tex; //Slightly faster this way because it can be calculated while we calculate noise.
  
  	colorInput.rgb = tex2D(colorsampler, (2.0 * fExplosionRadius * PixelSize) * noise + tex).rgb;
  
 
  	return colorInput;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Initializing pass which converts LDR image to HDR space														     //
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
float4 PS_ME_Init(VS_OUTPUT_POST IN) : COLOR 
{
	float mask = 1.0f;
#if(USE_HUD_MASKING==1)
	mask = tex2D(SamplerMask, IN.txcoord.xy).x;
#endif
	return tex2D(SamplerLDR, IN.txcoord.xy)*mask;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Ambient Occlusion													     //
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
float4 PS_ME_SSAO(VS_OUTPUT_POST IN) : COLOR
{
	IN.txcoord.xy /= AO_TEXSCALE;
	if(IN.txcoord.x > 1.0 || IN.txcoord.y > 1.0) discard;
	//global variables
	float depth		= tex2D(SamplerDepth, IN.txcoord.xy).x;
	float fSceneDepthP 	= GetLinearDepth(depth);
#if( AO_SHARPNESS_DETECT == 1)
	float blurkey = fSceneDepthP;
#else
	float blurkey = dot(GetNormalFromDepth(fSceneDepthP, IN.txcoord.xy).xyz,0.333)*0.1;
#endif
	if(fSceneDepthP > min(0.9999,AO_FADE_END)) return float4(0.5,0.5,0.5,blurkey);
	float offsetScale = fSSAOSamplingRange/10000;
	float fSSAODepthClip = 10000000.0;
	float3 vRotation = tex2Dlod(SamplerNoise, float4(IN.txcoord.xy, 0, 0)).rgb - 0.5f;
	
	float3x3 matRotate;
	float hao = 1.0f / (1.0f + vRotation.z);
	matRotate._m00 =  hao * vRotation.y * vRotation.y + vRotation.z;
	matRotate._m01 = -hao * vRotation.y * vRotation.x;
	matRotate._m02 = -vRotation.x;
	matRotate._m10 = -hao * vRotation.y * vRotation.x;
	matRotate._m11 =  hao * vRotation.x * vRotation.x + vRotation.z;
	matRotate._m12 = -vRotation.y;
	matRotate._m20 =  vRotation.x;
	matRotate._m21 =  vRotation.y;
	matRotate._m22 =  vRotation.z;
	float fOffsetScaleStep = 1.0f + 2.4f / iSSAOSamples;
	float fAccessibility = 0;
	int Sample_Scaled = iSSAOSamples;
	#if(SSAO_SmartSampling==1)
	if(fSceneDepthP > 0.5) Sample_Scaled=max(8,round(Sample_Scaled*0.5));
	if(fSceneDepthP > 0.8) Sample_Scaled=max(8,round(Sample_Scaled*0.5));
	#endif
	
	float fAtten = 5000.0/fSSAOSamplingRange/(1.0+fSceneDepthP*10.0);
	[loop]
	for (int i = 0 ; i < (Sample_Scaled / 8) ; i++)
	for (int x = -1 ; x <= 1 ; x += 2)
	for (int y = -1 ; y <= 1 ; y += 2)
	for (int z = -1 ; z <= 1 ; z += 2) {
		//Create offset vector
		float3 vOffset = normalize(float3(x, y, z)) * (offsetScale *= fOffsetScaleStep);
		//Rotate the offset vector
		float3 vRotatedOffset = mul(vOffset, matRotate);
		//Center pixel's coordinates in screen space
		float3 vSamplePos = float3(IN.txcoord.xy, fSceneDepthP);
 
		//Offset sample point
		vSamplePos += float3(vRotatedOffset.xy, vRotatedOffset.z * fSceneDepthP);
		//Read sample point depth
		float fSceneDepthS = GetLinearDepth(tex2Dlod(SamplerDepth, float4(vSamplePos.xy,0,0)).x);
		//Discard if depth equals max
		if (fSceneDepthS >= fSSAODepthClip)
			fAccessibility += 1.0f;
		else {
			//Compute accessibility factor
			float fDepthDist = abs(fSceneDepthP - fSceneDepthS);
			float fRangeIsInvalid = saturate(fDepthDist*fAtten);
			fAccessibility += lerp(fSceneDepthS > vSamplePos.z, 0.5f, fRangeIsInvalid);
		}
	}
 
	//Compute average accessibility
	fAccessibility = fAccessibility / Sample_Scaled;
	return float4(fAccessibility.xxx,blurkey);
}
float4 PS_ME_RayAO(VS_OUTPUT_POST IN) : COLOR	
{
	IN.txcoord.xy /= AO_TEXSCALE;
	if(IN.txcoord.x > 1.0 || IN.txcoord.y > 1.0) discard;
	float3	avOffsets [78] =
	{
	float3(0.2196607,0.9032637,0.2254677),
	float3(0.05916681,0.2201506,-0.1430302),
	float3(-0.4152246,0.1320857,0.7036734),
	float3(-0.3790807,0.1454145,0.100605),
	float3(0.3149606,-0.1294581,0.7044517),
	float3(-0.1108412,0.2162839,0.1336278),
	float3(0.658012,-0.4395972,-0.2919373),
	float3(0.5377914,0.3112189,0.426864),
	float3(-0.2752537,0.07625949,-0.1273409),
	float3(-0.1915639,-0.4973421,-0.3129629),
	float3(-0.2634767,0.5277923,-0.1107446),
	float3(0.8242752,0.02434147,0.06049098),
	float3(0.06262707,-0.2128643,-0.03671562),
	float3(-0.1795662,-0.3543862,0.07924347),
	float3(0.06039629,0.24629,0.4501176),
	float3(-0.7786345,-0.3814852,-0.2391262),
	float3(0.2792919,0.2487278,-0.05185341),
	float3(0.1841383,0.1696993,-0.8936281),
	float3(-0.3479781,0.4725766,-0.719685),
	float3(-0.1365018,-0.2513416,0.470937),
	float3(0.1280388,-0.563242,0.3419276),
	float3(-0.4800232,-0.1899473,0.2398808),
	float3(0.6389147,0.1191014,-0.5271206),
	float3(0.1932822,-0.3692099,-0.6060588),
	float3(-0.3465451,-0.1654651,-0.6746758),
	float3(0.2448421,-0.1610962,0.13289366),
	float3(0.2448421,0.9032637,0.24254677),
	float3(0.2196607,0.2201506,-0.18430302),
	float3(0.05916681,0.1320857,0.70036734),
	float3(-0.4152246,0.1454145,0.1800605),
	float3(-0.3790807,-0.1294581,0.78044517),
	float3(0.3149606,0.2162839,0.17336278),
	float3(-0.1108412,-0.4395972,-0.269619373),
	float3(0.658012,0.3112189,0.4267864),
	float3(0.5377914,0.07625949,-0.12773409),
	float3(-0.2752537,-0.4973421,-0.31629629),
	float3(-0.1915639,0.5277923,-0.17107446),
	float3(-0.2634767,0.02434147,0.086049098),
	float3(0.8242752,-0.2128643,-0.083671562),
	float3(0.06262707,-0.3543862,0.007924347),
	float3(-0.1795662,0.24629,0.44501176),
	float3(0.06039629,-0.3814852,-0.248391262),
	float3(-0.7786345,0.2487278,-0.065185341),
	float3(0.2792919,0.1696993,-0.84936281),
	float3(0.1841383,0.4725766,-0.7419685),
	float3(-0.3479781,-0.2513416,0.670937),
	float3(-0.1365018,-0.563242,0.36419276),
	float3(0.1280388,-0.1899473,0.23948808),
	float3(-0.4800232,0.1191014,-0.5271206),
	float3(0.6389147,-0.3692099,-0.5060588),
	float3(0.1932822,-0.1654651,-0.62746758),
	float3(-0.3465451,-0.1610962,0.4289366),
	float3(0.2448421,-0.1610962,0.2254677),
	float3(0.2196607,0.9032637,-0.1430302),
	float3(0.05916681,0.2201506,0.7036734),
	float3(-0.4152246,0.1320857,0.100605),
	float3(-0.3790807,0.3454145,0.7044517),
	float3(0.3149606,-0.4294581,0.1336278),
	float3(-0.1108412,0.3162839,-0.2919373),
	float3(0.658012,-0.2395972,0.426864),
	float3(0.5377914,0.33112189,-0.1273409),
	float3(-0.2752537,0.47625949,-0.3129629),
	float3(-0.1915639,-0.3973421,-0.1107446),
	float3(-0.2634767,0.2277923,0.06049098),
	float3(0.8242752,-0.3434147,-0.03671562),
	float3(0.06262707,-0.4128643,0.07924347),
	float3(-0.1795662,-0.3543862,0.4501176),
	float3(0.06039629,0.24629,-0.2391262),
	float3(-0.7786345,-0.3814852,-0.05185341),
	float3(0.2792919,0.4487278,-0.8936281),
	float3(0.1841383,0.3696993,-0.719685),
	float3(-0.3479781,0.2725766,0.470937),
	float3(-0.1365018,-0.5513416,0.3419276),
	float3(0.1280388,-0.163242,0.2398808),
	float3(-0.4800232,-0.3899473,-0.5271206),
	float3(0.6389147,0.3191014,-0.6060588),
	float3(0.1932822,-0.1692099,-0.6746758),
	float3(-0.3465451,-0.2654651,0.1289366)
	};
	float2 vOutSum;
	float3 vRandom, vReflRay, vViewNormal;
	float fCurrDepth, fSampleDepth, fDepthDelta, fAO;
	float depth = tex2D(SamplerDepth, IN.txcoord.xy).x;
	fCurrDepth  = GetLinearDepth(depth);
#if( AO_SHARPNESS_DETECT == 1)
	float blurkey = fCurrDepth;
#else
	float blurkey = dot(GetNormalFromDepth(fCurrDepth, IN.txcoord.xy).xyz,0.333)*0.1;
#endif
	if(fCurrDepth>min(0.9999,AO_FADE_END)) return float4(1.0,1.0,1.0,blurkey);
	vViewNormal = GetNormalFromDepth(fCurrDepth, IN.txcoord.xy);
	vRandom 	= GetRandomVector(IN.txcoord);
	fAO = 0;
	for(int s = 0; s < iRayAOSamples; s++) {
		vReflRay = reflect(avOffsets[s], vRandom);
		
		float fFlip = sign(dot(vViewNormal,vReflRay));
        	vReflRay   *= fFlip;
		
		float sD = fCurrDepth - (vReflRay.z * fRayAOSamplingRange);
		fSampleDepth = GetLinearDepth(tex2Dlod(SamplerDepth, float4(saturate(IN.txcoord.xy + (fRayAOSamplingRange * vReflRay.xy / fCurrDepth)),0,0)).x);
		fDepthDelta = saturate(sD - fSampleDepth);
		fDepthDelta *= 1-smoothstep(0,fRayAOMaxDepth,fDepthDelta);
		if ( fDepthDelta > fRayAOMinDepth && fDepthDelta < fRayAOMaxDepth)
			fAO += pow(1 - fDepthDelta, 2.5);
	}
	vOutSum.x = saturate(1 - (fAO / (float)iRayAOSamples) + fRayAOSamplingRange);
	return float4(vOutSum.xxx,blurkey);
}
float3 GetEyePosition(in float2 uv, in float eye_z) {
	uv = (uv * float2(2.0, -2.0) - float2(1.0, -1.0));
	float3 pos = float3(uv * InvFocalLen * eye_z, eye_z);
	return pos;
}
float2 GetRandom2_10(in float2 uv) {
	float noiseX = (frac(sin(dot(uv, float2(12.9898,78.233) * 2.0)) * 43758.5453));
	float noiseY = sqrt(1 - noiseX * noiseX);
	return float2(noiseX, noiseY);
}
float4 PS_ME_HBAO(VS_OUTPUT_POST IN) : COLOR	
{
	IN.txcoord.xy /= AO_TEXSCALE;
	if(IN.txcoord.x > 1.0 || IN.txcoord.y > 1.0) discard;
	float depth = GetLinearDepth(tex2D(SamplerDepth, IN.txcoord.xy).x);
#if( AO_SHARPNESS_DETECT == 1)
	float blurkey = depth;
#else
	float blurkey = dot(GetNormalFromDepth(depth, IN.txcoord.xy).xyz,0.333)*0.1;
#endif
	if(depth > min(0.9999,AO_FADE_END)) return float4(1.0,1.0,1.0,blurkey);
	float2 sample_offset[8] =
	{
		float2(1, 0),
		float2(0.7071f, 0.7071f),
		float2(0, 1),
		float2(-0.7071f, 0.7071f),
		float2(-1, 0),
		float2(-0.7071f, -0.7071f),
		float2(0, -1),
		float2(0.7071f, -0.7071f)
	};
	float3 pos = GetEyePosition(IN.txcoord.xy, depth);
	float3 dx = ddx(pos);
	float3 dy = ddy(pos);
	float3 norm = normalize(cross(dx,dy));
 
	float sample_depth=0;
	float3 sample_pos=0;
 
	float ao=0;
	float s=0.0;
 
	float2 rand_vec = GetRandom2_10(IN.txcoord.xy);
	float2 sample_vec_divisor = InvFocalLen*depth/(fHBAOSamplingRange*float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT));
	float2 sample_center = IN.txcoord.xy;
 
	for (int i = 0; i < 8; i++)
	{
		float theta,temp_theta,temp_ao,curr_ao = 0;
		float3 occlusion_vector = 0.0;
 
		float2 sample_vec = reflect(sample_offset[i], rand_vec);
		sample_vec /= sample_vec_divisor;
		float2 sample_coords = (sample_vec*float2(1,(float)BUFFER_WIDTH/(float)BUFFER_HEIGHT))/iHBAOSamples;
 
		for (int k = 1; k <= iHBAOSamples; k++)
		{
			sample_depth = GetLinearDepth(tex2Dlod(SamplerDepth, float4(sample_center + sample_coords*(k-0.5*(i%2)),0,0)).x);
			sample_pos = GetEyePosition(sample_center + sample_coords*(k-0.5*(i%2)), sample_depth);
			occlusion_vector = sample_pos - pos;
			temp_theta = dot( norm, normalize(occlusion_vector) );			
 
			if (temp_theta > theta)
			{
				theta = temp_theta;
				temp_ao = 1-sqrt(1 - theta*theta );
				ao += (1/ (1 + fHBAOAttenuation * pow(length(occlusion_vector)/fHBAOSamplingRange*5000,2)) )*(temp_ao-curr_ao);
				curr_ao = temp_ao;
			}
		}
		s += 1;
	}
 
	ao /= max(0.00001,s);
 	ao = 1.0-ao*fHBAOAmount;
	ao = clamp(ao,fHBAOClamp,1);
	return float4(ao.xxx, blurkey);
}
float tangent(float3 P, float3 S)
{
    	return (P.z - S.z) / length(S.xy - P.xy);
}
float3 uv_to_eye(float2 uv, float eye_z)
{
    	uv = uv * float2(2.0, -2.0) - float2(1.0, -1.0); // uv (0, 1) to (-1, 1)
    	return float3(uv /* invFocalLength */ * eye_z, eye_z); // Position in view space	
}
float3 fetch_eye_pos(float2 uv)
{
	float z = GetLinearDepth(tex2Dlod(SamplerDepth, float4(uv, 0, 0)).x); // Single channel zbuffer texture
    	return uv_to_eye(uv, z);
}
float3 min_diff(float3 P, float3 Pr, float3 Pl)
{
    	float3 V1 = Pr - P;
    	float3 V2 = P - Pl;
    	return (dot(V1,V1) < dot(V2,V2)) ? V1 : V2;
}
float Falloff(float r)
{
	return 1.0f - fRayHBAO_Attenuation * r * r;
}
float2 snap_uv_offset(float2 uv)
{
    	return round(uv * float2(BUFFER_WIDTH, BUFFER_HEIGHT)) * float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT);
}
float2 snap_uv_coord(float2 uv)
{
    	return uv - (frac(uv * float2(BUFFER_WIDTH, BUFFER_HEIGHT)) - 0.5f) * float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT);
}
float tan_to_sin(float x)
{
    	return x / sqrt(1.0f + x*x);
}
float tangent(float3 T)
{
    	return -T.z / length(T.xy);
}
float2 rotate_direction(float2 Dir, float2 CosSin)
{
    	return float2(Dir.x * CosSin.x - Dir.y * CosSin.y, 
                Dir.x * CosSin.y + Dir.y * CosSin.x);
}
float AccumulatedHorizonOcclusionHighQuality(float2 deltaUV, 
                                             float2 uv0, 
                                             float3 P, 
                                             float numSteps, 
                                             float randstep,
                                             float3 dPdu,
                                             float3 dPdv)
{
    	// Jitter starting point within the first sample distance
    	float2 uv = (uv0 + deltaUV) + randstep * deltaUV;
    
    	// Snap first sample uv and initialize horizon tangent
    	float2 snapped_duv = snap_uv_offset(uv - uv0);
	float3 T = snapped_duv.xxx * dPdu + snapped_duv.yyy * dPdv;	
    	float tanH = tangent(T) + fRayHBAO_AngleBiasTan;
    	float ao = 0;
    	float h0 = 0;
    	float3 occluderRadiance = 0;
	[loop]
    	for(float j = 0; j < numSteps; ++j)
	{
        	float2 snapped_uv = snap_uv_coord(uv);
        	float3 S = fetch_eye_pos(snapped_uv);
		// next uv in image space.
		uv += deltaUV;
        	// Ignore any samples outside the radius of influence
        	float d2 = dot(S-P,S-P);
		
		[flatten]
        	if (d2 < fRayHBAO_SampleRadius)
		{ 
            		float tanS = tangent(P, S);
            		[flatten]
            		if (tanS > tanH) // Is this height is bigger than the bigger height of this direction so far then
			{
                		// Compute tangent vector associated with snapped_uv
                	float2 snapped_duv2 = snapped_uv - uv0;
			float3 T2 = snapped_duv2.xxx * dPdu + snapped_duv2.yyy * dPdv;	//2 for faster compilation.
                	float tanT = tangent(T2) + fRayHBAO_AngleBiasTan;
                	// Compute AO between tangent T and sample S
                	float sinS = tan_to_sin(tanS);
                	float sinT = tan_to_sin(tanT);
                	float r = sqrt(d2) / fRayHBAO_SampleRadius;
                	float h = sinS - sinT;
			float falloff = Falloff(r);
                	ao += falloff * (h - h0);
                	h0 = h;
                	// Update the current horizon angle
                	tanH = tanS;
            		}
        	}
    	}
    	return ao;
}
float4 PS_ME_RayHBAO(VS_OUTPUT_POST IN) : COLOR
{
	IN.txcoord.xy /= AO_TEXSCALE;
	if(IN.txcoord.x > 1.0 || IN.txcoord.y > 1.0) discard;
	
	float depth = GetLinearDepth(tex2D(SamplerDepth, IN.txcoord.xy).x); 
#if( AO_SHARPNESS_DETECT == 1)
	float blurkey = depth;
#else
	float blurkey = dot(GetNormalFromDepth(depth, IN.txcoord.xy).xyz,0.333)*0.1;
#endif
	if(depth > min(0.9999,AO_FADE_END)) return float4(1.0,1.0,1.0,blurkey);
	float3 P = uv_to_eye(IN.txcoord.xy, depth);	
    	float2 step_size = 0.5 * fRayHBAO_SampleRadius / P.z; // Project radius
   
    	float numSteps = min (iRayHBAO_StepCount, min(step_size.x * BUFFER_WIDTH, step_size.y * BUFFER_HEIGHT));	
	step_size = step_size / ( numSteps + 1 );
    
    	float3 Pr, Pl, Pt, Pb;
		
	// Doesn't use normals
	Pr = fetch_eye_pos(IN.txcoord.xy + float2( BUFFER_RCP_WIDTH,  0));
	Pl = fetch_eye_pos(IN.txcoord.xy + float2(-BUFFER_RCP_WIDTH,  0));
	Pt = fetch_eye_pos(IN.txcoord.xy + float2(0, BUFFER_RCP_HEIGHT));
	Pb = fetch_eye_pos(IN.txcoord.xy + float2(0, -BUFFER_RCP_HEIGHT));
    	// Screen-aligned basis for the tangent plane
    	float3 dPdu = min_diff(P, Pr, Pl);
    	float3 dPdv = min_diff(P, Pt, Pb) * (BUFFER_HEIGHT * BUFFER_RCP_WIDTH);
    	// (cos(alpha),sin(alpha),jitter)
    	float3 rand = tex2D(SamplerNoise, IN.txcoord.xy*5).rgb; 
		
	float ao = 0;
    	float alpha = 2.0f * 3.1416 / iRayHBAO_StepDirections;	
	
	// High Quality
	for (int d = 0; d < iRayHBAO_StepDirections; d++) 
	{
		float angle = alpha * d;
		float2 dir = float2(cos(angle), sin(angle));
		float2 deltaUV = rotate_direction(dir, rand.xy) * step_size.xy;
		ao += AccumulatedHorizonOcclusionHighQuality(deltaUV, IN.txcoord.xy, P, numSteps, rand.z, dPdu, dPdv);
	}
		
	float result = saturate(1.0 - ao / iRayHBAO_StepDirections * 2.0);
	return float4(result.xxx,blurkey);
}
float3 GetSAO_CSPosition(float2 S, float z)
{
	//hardcoded FoV. Don't ask me but even single degree differences HEAVILY affect visual result
	//to a point where AO isn't applied or it's way too strong or whatever. Better leave it.
	float nearZ = 0.1; float farZ = 100.0; float vFOV = 68.0;
	float4x4 matProjection = float4x4(
  	1.0f / (aspect * tan(vFOV / 2.0f)),  0.0f,                     0.0f,                   0.0f,
  	0.0f,                                1.0f / tan(vFOV / 2.0f),  0.0f,                   0.0f,
  	0.0f,                                0.0f,                     farZ / (farZ - nearZ),         1.0f,
  	0.0f,                                0.0f,                     (farZ * nearZ) / (nearZ - farZ),  0.0f
	);
	float4 projInfo;
	projInfo.x = -2.0f / ((float)BUFFER_WIDTH * matProjection._11);
	projInfo.y = -2.0f / ((float)BUFFER_HEIGHT * matProjection._22),
	projInfo.z = ((1.0f - matProjection._13) / matProjection._11) + projInfo.x * 0.5f;
	projInfo.w = ((1.0f + matProjection._23) / matProjection._22) + projInfo.y * 0.5f;
	return float3(( (S.xy * float2(BUFFER_WIDTH,BUFFER_HEIGHT)) * projInfo.xy + projInfo.zw) * z, z);
}
float2 GetSAO_TapLocation(int sampleNumber, float spinAngle, out float ssR)
{
	uint ROTATIONS [98] = { 1, 1, 2, 3, 2, 5, 2, 3, 2,
	3, 3, 5, 5, 3, 4, 7, 5, 5, 7,
	9, 8, 5, 5, 7, 7, 7, 8, 5, 8,
	11, 12, 7, 10, 13, 8, 11, 8, 7, 14,
	11, 11, 13, 12, 13, 19, 17, 13, 11, 18,
	19, 11, 11, 14, 17, 21, 15, 16, 17, 18,
	13, 17, 11, 17, 19, 18, 25, 18, 19, 19,
	29, 21, 19, 27, 31, 29, 21, 18, 17, 29,
	31, 31, 23, 18, 25, 26, 25, 23, 19, 34,
	19, 27, 21, 25, 39, 29, 17, 21, 27 };
	uint NUM_SPIRAL_TURNS = ROTATIONS[iSAOSamples-1];
    	// Radius relative to ssR
    	float alpha = float(sampleNumber + 0.5) * (1.0 / iSAOSamples);
    	float angle = alpha * (NUM_SPIRAL_TURNS * 6.28) + spinAngle;
    	ssR = alpha;
    	float sin_v, cos_v;
    	sincos(angle, sin_v, cos_v);
    	return float2(cos_v, sin_v);
}
float GetSAO_CurveDepth(float depth)
{
	return 202.0 / (-99.0 * depth + 101.0);
}
float3 GetSAO_Position(float2 ssPosition)
{
    	float3 Position;
	Position.z = GetSAO_CurveDepth(tex2Dlod(SamplerDepth, float4(ssPosition.xy,0,0)).x);
	Position = GetSAO_CSPosition(ssPosition, Position.z);
    	return Position;
}
float3 GetSAO_OffsetPosition(float2 ssC, float2 unitOffset, float ssR)
{
    	float2 ssP = ssR*unitOffset + ssC;
	float3 P;
	P.z = GetSAO_CurveDepth(tex2Dlod(SamplerDepth, float4(ssP.xy,0,0)).x);
	P = GetSAO_CSPosition(ssP, P.z);
   	return P;
}
float GetSAO_SampleAO(in float2 ssC, in float3 C, in float3 n_C, in float ssDiskRadius, in int tapIndex, in float randomPatternRotationAngle)
{
    	float ssR;
    	float2 unitOffset = GetSAO_TapLocation(tapIndex, randomPatternRotationAngle, ssR);
    	ssR *= ssDiskRadius;
    	float3 Q = GetSAO_OffsetPosition(ssC, unitOffset, ssR);
	float3 v = Q - C;
	float vv = dot(v, v);
    	float vn = dot(v, n_C);
	float f = max(1.0 - vv * (1.0 / fSAORadius), 0.0); 
	return f * max((vn - fSAOBias) * rsqrt( vv), 0.0);	
}
float4 PS_ME_SAO(VS_OUTPUT_POST IN) : COLOR 
{
	IN.txcoord.xy /= AO_TEXSCALE;
	if(IN.txcoord.x > 1.0 || IN.txcoord.y > 1.0) discard;
	
	float depth = GetLinearDepth(tex2D(SamplerDepth, IN.txcoord.xy).x); 
#if( AO_SHARPNESS_DETECT == 1)
	float blurkey = depth;
#else
	float blurkey = dot(GetNormalFromDepth(depth, IN.txcoord.xy).xyz,0.333)*0.1;
#endif
	if(depth > min(0.9999,AO_FADE_END)) return float4(1.0,1.0,1.0,blurkey);
    	float3 ssPosition = GetSAO_Position(IN.txcoord.xy);
	float rotAngle = frac(sin(IN.txcoord.xy.x + IN.txcoord.xy.y * 543.31) *  493013.0) * 10.0;
	float3 ssNormals = normalize(cross(normalize(ddy(ssPosition)), normalize(ddx(ssPosition))));
	float ssDiskRadius = fSAORadius / max(ssPosition.z,0.1f);
   	float sum = 0.0;
    	[unroll]
    	for (int i = 0; i < iSAOSamples; ++i) 
    	{
         	sum += GetSAO_SampleAO(IN.txcoord.xy, ssPosition, ssNormals, ssDiskRadius, i, rotAngle);
    	}
	
	sum /= pow(fSAORadius,6.0);
	float A = pow(max(0.0, 1.0 - sqrt(sum * (3.0 / iSAOSamples))), fSAOIntensity);
	A = (pow(A, 0.2) + 1.2 * A*A*A*A) / 2.2;
	float ao = lerp(1.0, A, fSAOClamp);
	return float4(ao.xxx,blurkey);
}
float4 PS_ME_AOBlurV(VS_OUTPUT_POST IN) : COLOR 
{
	//It's better to do this here, upscaling must produce artifacts and upscale-> blur is better than blur -> upscale
	//besides: code is easier an I'm very lazy :P
	IN.txcoord.xy *= AO_TEXSCALE;
	float  sum,totalweight=0;
	float4 base = tex2D(SamplerOcclusion1, IN.txcoord.xy), temp=0;
	
	[loop]
	for (int r = -AO_BLUR_STEPS; r <= AO_BLUR_STEPS; ++r) 
	{
		float2 axis = float2(0.0, 1.0);
		temp = tex2D(SamplerOcclusion1, IN.txcoord.xy + axis * PixelSize * r);
		float weight = AO_BLUR_STEPS-abs(r); 
		weight *= max(0.0, 1.0 - (1000.0 * AO_SHARPNESS) * abs(temp.w - base.w));
		sum += temp.x * weight;
		totalweight += weight;
	}
	return float4(sum / (totalweight+0.0001),0,0,base.w);
}
float4 PS_ME_AOBlurH(VS_OUTPUT_POST IN) : COLOR 
{
	float  sum,totalweight=0;
	float4 base = tex2D(SamplerOcclusion2, IN.txcoord.xy), temp=0;
	
	[loop]
	for (int r = -AO_BLUR_STEPS; r <= AO_BLUR_STEPS; ++r) 
	{
		float2 axis = float2(1.0, 0.0);
		temp = tex2D(SamplerOcclusion2, IN.txcoord.xy + axis * PixelSize * r);
		float weight = AO_BLUR_STEPS-abs(r); 
		weight *= max(0.0, 1.0 - (1000.0 * AO_SHARPNESS) * abs(temp.w - base.w));
		sum += temp.x * weight;
		totalweight += weight;
	}
	return float4(sum / (totalweight+0.0001),0,0,base.w);
}
float4 PS_ME_AOCombine(VS_OUTPUT_POST IN) : COLOR 
{
	float4 color = tex2D(SamplerHDR1, IN.txcoord.xy);
	float ao = tex2D(SamplerOcclusion1, IN.txcoord.xy).x;
#if( AO_METHOD == 1) //SSAO
	ao -= 0.5;
	if(ao < 0) ao *= fSSAODarkeningAmount;
	if(ao > 0) ao *= fSSAOBrighteningAmount;
	ao = 2 * saturate(ao+0.5);	
#endif
#if( AO_METHOD == 2)
	ao = pow(ao, fRayAOPower);
#endif
#if( AO_DEBUG == 1)
 #if(AO_METHOD == 1)	
	ao *= 0.5;
 #endif
	return ao;
#endif
#if(AO_LUMINANCE_CONSIDERATION == 1)
	float origlum = dot(color.xyz, 0.333);
	float aomult = smoothstep(AO_LUMINANCE_LOWER, AO_LUMINANCE_UPPER, origlum);
	ao = lerp(ao, 1.0, aomult);
#endif	
	float depth = GetLinearDepth(tex2D(SamplerDepth, IN.txcoord.xy).x); 
	ao = lerp(ao,1.0,smoothstep(AO_FADE_START,AO_FADE_END,depth));
	color.xyz *= ao;
	return color;
}
float4 PS_ME_SSGI(VS_OUTPUT_POST IN) : COLOR	
{
	IN.txcoord.xy /= AO_TEXSCALE;
	if(IN.txcoord.x > 1.0 || IN.txcoord.y > 1.0) discard;
	float depth = tex2D(SamplerDepth, IN.txcoord.xy).x;
	depth  = GetLinearDepth(depth);
	if(depth > min(0.9999,AO_FADE_END)) return float4(0.0,0.0,0.0,1.0);
	float giClamp = 0.0;
	float2 sample_offset[24] =
	{
		float2(-0.1376476f,  0.2842022f ),float2(-0.626618f ,  0.4594115f ),
		float2(-0.8903138f, -0.05865424f),float2( 0.2871419f,  0.8511679f ),
		float2(-0.1525251f, -0.3870117f ),float2( 0.6978705f, -0.2176773f ),
		float2( 0.7343006f,  0.3774331f ),float2( 0.1408805f, -0.88915f   ),
		float2(-0.6642616f, -0.543601f  ),float2(-0.324815f, -0.093939f   ),
		float2(-0.1208579f , 0.9152063f ),float2(-0.4528152f, -0.9659424f ),
		float2(-0.6059740f,  0.7719080f ),float2(-0.6886246f, -0.5380305f ),
		float2( 0.5380307f, -0.2176773f ),float2( 0.7343006f,  0.9999345f ),
		float2(-0.9976073f, -0.7969264f ),float2(-0.5775355f,  0.2842022f ),
		float2(-0.626618f ,  0.9115176f ),float2(-0.29818942f, -0.0865424f),
		float2( 0.9161239f,  0.8511679f ),float2(-0.1525251f, -0.07103951f ),
		float2( 0.7022788f, -0.823825f ),float2(0.60250657f,  0.64525909f )
	};
	float sample_radius[24] =
	{	
		0.5162497,0.2443335,
		0.1014819,0.1574599,
		0.6538922,0.5637644,
		0.6347278,0.2467654,
		0.5642318,0.0035689,
		0.6384532,0.3956547,
		0.7049623,0.3482861,
		0.7484038,0.2304858,
		0.0043161,0.5423726,
		0.5025704,0.4066662,
		0.2654198,0.8865175,
		0.9505567,0.9936577
	};
	float3 pos = GetEyePosition(IN.txcoord.xy, depth);
	float3 dx = ddx(pos);
	float3 dy = ddy(pos);
	float3 norm = normalize(cross(dx, dy));
	norm.y *= -1;
	float sample_depth;
	float4 gi = float4(0, 0, 0, 0);
	float is = 0, as = 0;
	float rangeZ = 5000;
	float2 rand_vec = GetRandom2_10(IN.txcoord.xy);
	float2 rand_vec2 = GetRandom2_10(-IN.txcoord.xy);
	float2 sample_vec_divisor = InvFocalLen * depth / (fSSGISamplingRange * PixelSize.xy);
	float2 sample_center = IN.txcoord.xy + norm.xy / sample_vec_divisor * float2(1, aspect);
	float ii_sample_center_depth = depth * rangeZ + norm.z * fSSGISamplingRange * 20;
	float ao_sample_center_depth = depth * rangeZ + norm.z * fSSGISamplingRange * 5;
	[fastopt]
	for (int i = 0; i < iSSGISamples; i++) {
		float2 sample_vec = reflect(sample_offset[i], rand_vec) / sample_vec_divisor;
		float2 sample_coords = sample_center + sample_vec *  float2(1, aspect);
		float  sample_depth = rangeZ * GetLinearDepth(tex2Dlod(SamplerDepth,float4(sample_coords.xy,0,0)).x);
 
		float ii_curr_sample_radius = sample_radius[i] * fSSGISamplingRange * 20;
		float ao_curr_sample_radius = sample_radius[i] * fSSGISamplingRange * 5;
 
		gi.a += clamp(0, ao_sample_center_depth + ao_curr_sample_radius - sample_depth, 2 * ao_curr_sample_radius);
		gi.a -= clamp(0, ao_sample_center_depth + ao_curr_sample_radius - sample_depth - fSSGIModelThickness, 2 * ao_curr_sample_radius);
 
		if ((sample_depth < ii_sample_center_depth + ii_curr_sample_radius) &&
		    (sample_depth > ii_sample_center_depth - ii_curr_sample_radius)) {
			float3 sample_pos = GetEyePosition(sample_coords, sample_depth);
			float3 unit_vector = normalize(pos - sample_pos);
 			gi.rgb += tex2Dlod(SamplerLDR, float4(sample_coords,0,0)).rgb;
		}
 
		is += 1.0f;
		as += 2.0f * ao_curr_sample_radius;
	}
 
	gi.rgb /= is * 5.0f;
	gi.a   /= as;
 
	gi.rgb = 0.0 + gi.rgb * fSSGIIlluminationMult;
	gi.a   = 1.0 - gi.a   * fSSGIOcclusionMult;
	gi.rgb = lerp(dot(gi.rgb, 0.333), gi.rgb, fSSGISaturation);
	return gi;
}
float4 PS_ME_GIBlurV(VS_OUTPUT_POST IN) : COLOR 
{
	IN.txcoord.xy *= AO_TEXSCALE;
	float4 sum=0;
	float totalweight=0;
	float4 base = tex2D(SamplerOcclusion1, IN.txcoord.xy), temp = 0;
	float depth = GetLinearDepth(tex2Dlod(SamplerDepth, float4(IN.txcoord.xy,0,0)).x);
#if( AO_SHARPNESS_DETECT == 1)
	float blurkey = depth;
#else
	float blurkey = dot(GetNormalFromDepth(depth, IN.txcoord.xy).xyz,0.333)*0.1;
#endif
	
	[loop]
	for (int r = -AO_BLUR_STEPS; r <= AO_BLUR_STEPS; ++r) 
	{
		float2 axis = float2(0, 1);
		temp = tex2D(SamplerOcclusion1, IN.txcoord.xy + axis * PixelSize * r);
		float tempdepth = GetLinearDepth(tex2Dlod(SamplerDepth, float4(IN.txcoord.xy + axis * PixelSize * r,0,0)).x);
#if( AO_SHARPNESS_DETECT == 1)
		float tempkey = tempdepth;
#else
		float tempkey = dot(GetNormalFromDepth(tempdepth, IN.txcoord.xy + axis * PixelSize * r).xyz,0.333)*0.1;
#endif
		float weight = AO_BLUR_STEPS-abs(r); 
		weight *= max(0.0, 1.0 - (1000.0 * AO_SHARPNESS) * abs(tempkey - blurkey));
		sum += temp * weight;
		totalweight += weight;
	}
	return sum / (totalweight+0.0001);
}
float4 PS_ME_GIBlurH(VS_OUTPUT_POST IN) : COLOR 
{
	float4 sum=0;
	float totalweight=0;
	float4 base = tex2D(SamplerOcclusion2, IN.txcoord.xy), temp = 0;
	float depth = GetLinearDepth(tex2Dlod(SamplerDepth, float4(IN.txcoord.xy,0,0)).x);
#if( AO_SHARPNESS_DETECT == 1)
	float blurkey = depth;
#else
	float blurkey = dot(GetNormalFromDepth(depth, IN.txcoord.xy).xyz,0.333)*0.1;
#endif
	
	[loop]
	for (int r = -AO_BLUR_STEPS; r <= AO_BLUR_STEPS; ++r) 
	{
		float2 axis = float2(1, 0);
		temp = tex2D(SamplerOcclusion2, IN.txcoord.xy + axis * PixelSize * r);
		float tempdepth = GetLinearDepth(tex2Dlod(SamplerDepth, float4(IN.txcoord.xy + axis * PixelSize * r,0,0)).x);
#if( AO_SHARPNESS_DETECT == 1)
		float tempkey = tempdepth;
#else
		float tempkey = dot(GetNormalFromDepth(tempdepth, IN.txcoord.xy + axis * PixelSize * r).xyz,0.333)*0.1;
#endif
		float weight = AO_BLUR_STEPS-abs(r); 
		weight *= max(0.0, 1.0 - (1000.0 * AO_SHARPNESS) * abs(tempkey - blurkey));
		sum += temp * weight;
		totalweight += weight;
	}
	return sum / (totalweight+0.0001);
}
float4 PS_ME_GICombine(VS_OUTPUT_POST IN) : COLOR 
{
	float4 color = tex2D(SamplerHDR1, IN.txcoord.xy);
	float4 gi = tex2D(SamplerOcclusion1, IN.txcoord.xy);
#if( AO_DEBUG == 1)
	return gi.wwww; //AO
#endif
#if( AO_DEBUG == 2)
	return gi.xyzz; //GI color
#endif	
#if(AO_LUMINANCE_CONSIDERATION == 1)
	float origlum = dot(color.xyz, 0.333);
	float aomult = smoothstep(AO_LUMINANCE_LOWER, AO_LUMINANCE_UPPER, origlum);
	gi.w = lerp(gi.w, 1.0, aomult);
	gi.xyz = lerp(gi.xyz,0.0, aomult);
#endif	
	float depth = GetLinearDepth(tex2D(SamplerDepth, IN.txcoord.xy).x); 
	gi.xyz = lerp(gi.xyz,0.0,smoothstep(AO_FADE_START,AO_FADE_END,depth));
	gi.w = lerp(gi.w,1.0,smoothstep(AO_FADE_START,AO_FADE_END,depth));
	color.xyz = (color.xyz+gi.xyz)*gi.w;
	return color;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Blurring/DOF/TiltShift												     //
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
float GetFocalDepth(float2 focalpoint)
{ 
 	float depthsum = 0;
 	float fcRadius = 0.00;
	for(int r=0;r<6;r++)
	{ 
 		float t = (float)r; 
 		t *= 3.1415*2/6; 
 		float2 coord = float2(cos(t),sin(t)); 
 		coord.y *= ScreenSize.z; 
 		coord *= fcRadius; 
 		float depth = GetLinearDepth(tex2Dlod(SamplerDepth,float4(coord+focalpoint,0,0)).x); 
 		depthsum+=depth; 
 	}
	depthsum = depthsum/6;
#if(DOF_MANUALFOCUS == 1)
	depthsum = DOF_MANUALFOCUSDEPTH;
#endif
	return depthsum; 
}
float4 PS_ME_CoC(VS_OUTPUT_POST IN) : COLOR //schreibt nach HDR2	
{
	float scenedepth = GetLinearDepth(tex2D(SamplerDepth, IN.txcoord.xy).x);
	float scenefocus =  GetFocalDepth(DOF_FOCUSPOINT);
	
	float depthdiff = abs(scenedepth-scenefocus);
	depthdiff = (scenedepth < scenefocus) ? pow(depthdiff, DOF_NEARBLURCURVE) : depthdiff;
	depthdiff = (scenedepth > scenefocus) ? pow(depthdiff, DOF_FARBLURCURVE) : depthdiff;
	float mask = 1.0f;
#if(USE_HUD_MASKING == 1)
	mask = tex2D(SamplerMask, IN.txcoord.xy).x;
#endif
	return saturate(float4(depthdiff,scenedepth,scenefocus,0))*mask;
}
//RING DOF
float4 GetColorDOF(sampler tex, float2 coords,float blur) //processing the sample
{
	float4 colDF = float4(1,1,1,1);
	colDF.x = tex2Dlod(tex,float4(coords + float2(0.0,1.0)*fRingDOFFringe*blur,0,0)).x;
	colDF.y = tex2Dlod(tex,float4(coords + float2(-0.866,-0.5)*fRingDOFFringe*blur,0,0)).y;
	colDF.z = tex2Dlod(tex,float4(coords + float2(0.866,-0.5)*fRingDOFFringe*blur,0,0)).z;
	return colDF;
}
float4 GetDOF(sampler tex, float2 coords, float blur) //processing the sample
{
	float4 colDF = tex2Dlod(tex,float4(coords,0,0));
	float lum = dot(colDF.xyz,LumCoeff);
	float thresh = max((lum-fRingDOFThreshold)*fRingDOFGain, 0.0);
	float3 nullcol = float3(0,0,0);
	colDF.xyz +=max(0,lerp(nullcol.xyz,colDF.xyz,thresh*blur));
	return colDF;
}
float4 PS_ME_RingDOF1(VS_OUTPUT_POST IN) : COLOR 
{
	float3 origCoC = tex2D(SamplerCoC, IN.txcoord.xy).xyz;	
	float2 discRadius = DOF_BLURRADIUS*PixelSize.xy*origCoC.x/iRingDOFRings;
	return GetColorDOF(SamplerHDR2,IN.txcoord.xy, discRadius.x);
}
float4 PS_ME_RingDOF2(VS_OUTPUT_POST IN) : COLOR 
{
	float CoC = tex2D(SamplerCoC, IN.txcoord.xy).x;	
	
	float2 discRadius = DOF_BLURRADIUS*PixelSize.xy*CoC/iRingDOFRings;
	
	float4 col = tex2D(SamplerHDR1, IN.txcoord.xy);
	
	if(discRadius.x/PixelSize.x > 0.25) //some optimization thingy
	{
	float s = 1.0;
	int ringsamples;
	float3 origCoC = tex2D(SamplerCoC, IN.txcoord.xy).xyz;
	[loop]
	for (int g = 1; g <= iRingDOFRings; g += 1)
	{
		ringsamples = g * iRingDOFSamples;
		[loop]
		for (int j = 0 ; j < ringsamples ; j += 1)
		{
			float step = PI*2.0 / ringsamples;
			float2 sampleoffset = discRadius.xy * float2(cos(j*step)*g, sin(j*step)*g);
			float3 sampleCoC = tex2Dlod(SamplerCoC, float4(IN.txcoord.xy + sampleoffset,0,0)).xyz;
			if(origCoC.y>origCoC.z && sampleCoC.x<CoC) sampleoffset = sampleoffset/CoC*sampleCoC.x;
			col.xyz += GetDOF(SamplerHDR1,IN.txcoord.xy + sampleoffset,CoC).xyz*lerp(1.0,g/iRingDOFRings,fRingDOFBias);  
			s += 1.0*lerp(1.0,g/iRingDOFRings,fRingDOFBias);
		}
	}
	col = col/s; //divide by sample count
	}
	
	return col;
}
//MAGIC DOF
float4 PS_ME_MagicDOF1(VS_OUTPUT_POST IN) : COLOR	
{
	float4 res,tapres;	
	float totalweight=0;
	res = tex2D(SamplerHDR2, IN.txcoord.xy);
	float3 origCoC = tex2D(SamplerCoC, IN.txcoord.xy).xyz;
	float2 discRadius = origCoC.x*PixelSize.xy*DOF_BLURRADIUS/iMagicDOFBlurQuality;
	
	int passnum = iMagicDOFBlurQuality;
	//Wilham Anggowo please keep your Fingers from this shader, I don't want to see it in ENB!
	res.xyz = 0;
		
	[loop]
	for (int i = -iMagicDOFBlurQuality; i <= iMagicDOFBlurQuality; ++i) 
	{
		float2 tapoffset = float2((float)i,0)*discRadius.xy;
		float3 sampleCoC = tex2Dlod(SamplerCoC, float4(IN.txcoord.xy + tapoffset,0,0)).xyz;
		if(origCoC.y>origCoC.z && sampleCoC.x<origCoC.x) tapoffset = tapoffset/origCoC.x*sampleCoC.x;
		tapres = tex2Dlod(SamplerHDR2, float4(IN.txcoord.xy+tapoffset,0,0));
		res.xyz += tapres.xyz;
		totalweight+=1;
	}
	res.xyz /= totalweight;
	return float4(res.xyz,1);
}
float4 PS_ME_MagicDOF2(VS_OUTPUT_POST IN) : COLOR	
{
	float4 res,tapres1,tapres2;	
	float totalweight=0;
	res = tex2D(SamplerHDR1, IN.txcoord.xy);
	float3 origcolor = res.xyz;
	
	float3 origCoC = tex2D(SamplerCoC, IN.txcoord.xy).xyz;
	float2 discRadius = origCoC.x*PixelSize.xy*DOF_BLURRADIUS/iMagicDOFBlurQuality;
	int passnum = iMagicDOFBlurQuality;
	int lodlevel = clamp(round(discRadius.x/6),0,3);
	res.xyz = 0;
		
	[loop]
	for (int i = -iMagicDOFBlurQuality; i <= iMagicDOFBlurQuality; ++i) 
	{
		float2 tapoffset1 = float2((float)i*discRadius.x*0.5,(float)i*discRadius.y*0.5*tan(60*PIOVER180));
		float2 tapoffset2 = float2(-tapoffset1.x,tapoffset1.y);
		float3 sampleCoC1 = tex2Dlod(SamplerCoC, float4(IN.txcoord.xy + tapoffset1,0,0)).xyz;
		float3 sampleCoC2 = tex2Dlod(SamplerCoC, float4(IN.txcoord.xy + tapoffset2,0,0)).xyz;
		if(origCoC.y>origCoC.z && sampleCoC1.x<origCoC.x) tapoffset1 = tapoffset1/origCoC.x*sampleCoC1.x; //never ask why I cam up with this. It works. Better than any masking I found but still not flawless.
		if(origCoC.y>origCoC.z && sampleCoC2.x<origCoC.x) tapoffset2 = tapoffset2/origCoC.x*sampleCoC2.x;
		tapres1 = tex2Dlod(SamplerHDR1, float4(IN.txcoord.xy+tapoffset1,0,lodlevel));
		tapres2 = tex2Dlod(SamplerHDR1, float4(IN.txcoord.xy+tapoffset2,0,lodlevel));
		totalweight += 1;
		res.xyz += pow(min(tapres1.xyz, tapres2.xyz),fMagicDOFColorCurve);
		}
	res.xyz /= totalweight;
	res.xyz = saturate(pow(saturate(res.xyz), 1/fMagicDOFColorCurve));
	
	return res;
}
//GP65CJ042 DOF
float4 PS_ME_GPDOF1(VS_OUTPUT_POST IN) : COLOR
{
	float4 res=tex2D(SamplerHDR2, IN.txcoord.xy);
	float4 origcolor=0;
	float3 origCoC = tex2D(SamplerCoC, IN.txcoord.xy).xyz;
	float2 discRadius = DOF_BLURRADIUS*PixelSize.xy*max(0,origCoC.x-0.1);//optimization to clean focus areas a bit
	float3 distortion=float3(-1.0, 0.0, 1.0);
	distortion*=fGPDOFChromaAmount;
	origcolor=tex2D(SamplerHDR2, IN.txcoord.xy + discRadius.xy*distortion.x);
	origcolor.w=smoothstep(0.0, origCoC.y, origcolor.w);
	res.x=lerp(res.x, origcolor.x, origcolor.w);
	
	origcolor=tex2D(SamplerHDR2, IN.txcoord.xy + discRadius.xy*distortion.z);
	origcolor.w=smoothstep(0.0, origCoC.y, origcolor.w);
	res.z=lerp(res.z, origcolor.z, origcolor.w);
	return res;
}
float4 PS_ME_GPDOF2(VS_OUTPUT_POST IN) : COLOR
{
	float4 res;
	float4 origcolor=tex2D(SamplerHDR1, IN.txcoord.xy);
	float3 origCoC = tex2D(SamplerCoC, IN.txcoord.xy).xyz;
	float2 discRadius = origCoC.x*DOF_BLURRADIUS*PixelSize.xy;
	res.xyz=origcolor.xyz;
	res.w=dot(res.xyz, 0.3333);
	res.w=max((res.w - fGPDOFBrightnessThreshold) * fGPDOFBrightnessMultiplier, 0.0);
	res.xyz*=(1.0 + res.w*origCoC.x);
	res.xyz*=lerp(1.0,0.0,fGPDOFBias);
	res.w=1.0;
	
	int sampleCycle=0;
	int sampleCycleCounter=0;
	int sampleCounterInCycle=0;
	
	#if ( bGPDOFPolygonalBokeh == 1)
		float basedAngle=360.0 / iGPDOFPolygonCount;
		float2 currentVertex;
		float2 nextVertex;
	
		int	dofTaps=iGPDOFQuality * (iGPDOFQuality + 1) * iGPDOFPolygonCount / 2.0;
	#else
		int	dofTaps=iGPDOFQuality * (iGPDOFQuality + 1) * 4;
	#endif
	
	for(int i=0; i < dofTaps; i++)
	{
		//dumb step incoming
		bool dothatstep=0;
		if(sampleCounterInCycle==0) dothatstep=1;
		if(sampleCycle!=0) 
		{
		if(sampleCounterInCycle % sampleCycle == 0) dothatstep=1;
		}
		//until here
		//ask yourself why so complicated? if(sampleCounterInCycle % sampleCycle == 0 ) gives warnings when sampleCycle=0
		//but it can only be 0 when sampleCounterInCycle is also 0 so it essentially is no division through 0 even if
		//the compiler believes it, it's 0/0 actually but without disabling shader optimizations this is the only way to workaround that.
		
		if(dothatstep==1)
		{
			sampleCounterInCycle=0;
			sampleCycleCounter++;
		
			#if ( bGPDOFPolygonalBokeh == 1)
				sampleCycle+=iGPDOFPolygonCount;
				currentVertex.xy=float2(1.0 , 0.0);
				sincos(basedAngle* 0.017453292, nextVertex.y, nextVertex.x);	
			#else	
				sampleCycle+=8;
			#endif
		}
		sampleCounterInCycle++;
		
		#if (bGPDOFPolygonalBokeh==1)
			float sampleAngle=basedAngle / float(sampleCycleCounter) * sampleCounterInCycle;
			float remainAngle=frac(sampleAngle / basedAngle) * basedAngle;
		
			if(remainAngle < 0.000001)
			{
				currentVertex=nextVertex;
				sincos((sampleAngle +  basedAngle) * 0.017453292, nextVertex.y, nextVertex.x);
			}
			float2 sampleOffset=lerp(currentVertex.xy, nextVertex.xy, remainAngle / basedAngle);
		#else
			float sampleAngle=0.78539816 / float(sampleCycleCounter) * sampleCounterInCycle;
			float2 sampleOffset;
			sincos(sampleAngle, sampleOffset.y, sampleOffset.x);
		#endif
		
		sampleOffset*=sampleCycleCounter / float(iGPDOFQuality);
		sampleOffset*=discRadius;
		float3 sampleCoC = tex2Dlod(SamplerCoC, float4(IN.txcoord.xy+sampleOffset.xy,0,0)).xyz;
		if(origCoC.y>origCoC.z && sampleCoC.x<origCoC.x) sampleOffset = sampleOffset/origCoC.x*sampleCoC.x;
		float4 tap=tex2Dlod(SamplerHDR1, float4(IN.txcoord.xy+sampleOffset.xy,0,0));
		tap.w=dot(tap.xyz, 0.3333);
		float brightMultipiler=max((tap.w - fGPDOFBrightnessThreshold) * fGPDOFBrightnessMultiplier, 0.0);
		tap.xyz*=(1.0 + brightMultipiler*origCoC.x);
		//res.w+=1.0 + fGPDOFBias * pow(float(sampleCycleCounter)/float(iGPDOFQuality), fGPDOFBiasCurve);
		float curvemult = lerp(1.0,pow(float(sampleCycleCounter)/float(iGPDOFQuality), fGPDOFBiasCurve),fGPDOFBias);
		res.xyz += tap.xyz*curvemult;
		res.w += curvemult;
	}
	res.xyz /= res.w;
	return res;
}
//MATSO DOF
float4 GetMatsoDOFCA(sampler col, float2 tex, float CoC)
{
	float3 chroma = pow(float3(0.5, 1.0, 1.5), fMatsoDOFChromaPow * CoC);
	float2 tr = ((2.0 * tex - 1.0) * chroma.r) * 0.5 + 0.5;
	float2 tg = ((2.0 * tex - 1.0) * chroma.g) * 0.5 + 0.5;
	float2 tb = ((2.0 * tex - 1.0) * chroma.b) * 0.5 + 0.5;
	
	float3 color = float3(tex2D(col, tr).r, tex2D(col, tg).g, tex2D(col, tb).b) * (1.0 - CoC);
	
	return float4(color, 1.0);
}
float4 GetMatsoDOFBlur(int axis, float2 coord, sampler SamplerHDRX)
{
	float4 res;
	float4 tcol = tex2D(SamplerHDRX, coord.xy);
	
	float3 origCoC = tex2D(SamplerCoC, coord.xy).xyz;
	float2 discRadius = origCoC.x*DOF_BLURRADIUS*PixelSize.xy*0.5/iMatsoDOFBokehQuality;
	int passnumber=1;
	float sf = 0;
	float2 tdirs[4] = { float2(-0.306, 0.739), float2(0.306, 0.739), float2(-0.739, 0.306), float2(-0.739, -0.306) };
#if (bMatsoDOFBokehEnable==1)
	float wValue = (1.0 + pow(length(tcol.rgb) + 0.1, fMatsoDOFBokehCurve)) * (1.0 - fMatsoDOFBokehLight);	// special recipe from papa Matso ;)
#else
	float wValue = 1.0;
#endif
	for (int i = -iMatsoDOFBokehQuality; i < iMatsoDOFBokehQuality; i++)
	{
		float2 taxis =  tdirs[axis];
		taxis.x = cos(fMatsoDOFBokehAngle*PIOVER180)*taxis.x-sin(fMatsoDOFBokehAngle*PIOVER180)*taxis.y;
		taxis.y = sin(fMatsoDOFBokehAngle*PIOVER180)*taxis.x+cos(fMatsoDOFBokehAngle*PIOVER180)*taxis.y;
		
		float2 tdir = (float)i * taxis * discRadius;
		float2 tcoord = coord.xy + tdir.xy;
#if(bMatsoDOFChromaEnable == 1)
		float4 ct = GetMatsoDOFCA(SamplerHDRX, tcoord.xy, discRadius.x);
#else
		float4 ct = tex2D(SamplerHDRX, tcoord.xy);
#endif
#if (bMatsoDOFBokehEnable == 0)
		float w = 1.0 + abs(offset[i]);	// weight blur for better effect
#else	
	// my own pseudo-bokeh weighting
		float b = dot(ct.rgb,0.333) + length(ct.rgb) + 0.1;
		float w = pow(b, fMatsoDOFBokehCurve) + abs((float)i);
#endif
		tcol += ct * w;
		wValue += w;
	}
	tcol /= wValue;
	res.xyz = tcol.xyz;
	res.w = 1.0;
	return res;
}
float4 PS_ME_MatsoDOF1(VS_OUTPUT_POST IN) : COLOR
{
	return GetMatsoDOFBlur(2, IN.txcoord.xy, SamplerHDR2);	
}
float4 PS_ME_MatsoDOF2(VS_OUTPUT_POST IN) : COLOR
{
	return GetMatsoDOFBlur(3, IN.txcoord.xy, SamplerHDR1);	
}
float4 PS_ME_MatsoDOF3(VS_OUTPUT_POST IN) : COLOR
{
	return GetMatsoDOFBlur(0, IN.txcoord.xy, SamplerHDR2);	
}
float4 PS_ME_MatsoDOF4(VS_OUTPUT_POST IN) : COLOR
{
	return GetMatsoDOFBlur(1, IN.txcoord.xy, SamplerHDR1);	
}
float4 PS_ME_Blur(VS_OUTPUT_POST IN) : COLOR	
{
	return tex2D(SamplerHDR1, IN.txcoord.xy);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Bloom 													     	     //
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
float4 PS_ME_BloomPrePass(VS_OUTPUT_POST IN) : COLOR
{
	
	float4 bloom=0.0;
	float2 bloomuv;
	float2 offset[4]=
	{
		float2(1.0, 1.0),
		float2(1.0, 1.0),
		float2(-1.0, 1.0),
		float2(-1.0, -1.0)
	};
	for (int i=0; i<4; i++)
	{
		bloomuv.xy=offset[i]*PixelSize.xy*2;
		bloomuv.xy=IN.txcoord.xy + bloomuv.xy;
		float4 tempbloom=tex2Dlod(SamplerLDR, float4(bloomuv.xy, 0, 0));
		tempbloom.w = max(0,dot(tempbloom.xyz,0.333)-fAnamFlareThreshold);
		tempbloom.xyz = max(0, tempbloom.xyz-fBloomThreshold); 
#if(USE_HUD_MASKING == 1)
		float mask = tex2Dlod(SamplerMask, float4(bloomuv.xy, 0, 0)).x;
		tempbloom *= mask;
#endif
		bloom+=tempbloom;
	}
	bloom *= 0.25;
	return bloom;
}
float4 PS_ME_BloomPass1(VS_OUTPUT_POST IN) : COLOR
{
	float4 bloom=0.0;
	float2 bloomuv;
	float2 offset[8]=
	{
		float2(1.0, 1.0),
		float2(0.0, -1.0),
		float2(-1.0, 1.0),
		float2(-1.0, -1.0),
		float2(0.0, 1.0),
		float2(0.0, -1.0),
		float2(1.0, 0.0),
		float2(-1.0, 0.0)
	};
	for (int i=0; i<8; i++)
	{
		bloomuv.xy=offset[i]*PixelSize.xy*4;
		bloomuv.xy=IN.txcoord.xy + bloomuv.xy;
		float4 tempbloom=tex2Dlod(SamplerBloom1, float4(bloomuv.xy, 0, 0));
		bloom+=tempbloom;
	}
	bloom *= 0.125;
	return bloom;
}
float4 PS_ME_BloomPass2(VS_OUTPUT_POST IN) : COLOR
{
	float4 bloom=0.0;
	float2 bloomuv;
	float2 offset[8]=
	{
		float2(0.707, 0.707),
		float2(0.707, -0.707),
		float2(-0.707, 0.707),
		float2(-0.707, -0.707),
		float2(0.0, 1.0),
		float2(0.0, -1.0),
		float2(1.0, 0.0),
		float2(-1.0, 0.0)
	};
	for (int i=0; i<8; i++)
	{
		bloomuv.xy=offset[i]*PixelSize.xy*8;
		bloomuv.xy=IN.txcoord.xy + bloomuv.xy;
		float4 tempbloom=tex2Dlod(SamplerBloom2, float4(bloomuv.xy, 0, 0));
		bloom+=tempbloom;
	}
	bloom *= 0.5; //to brighten up the sample, it will lose brightness in H/V gaussian blur 
	return bloom;
}
float4 PS_ME_BloomPass3(VS_OUTPUT_POST IN) : COLOR
{
	float4 bloom;
	bloom = GaussBlur22(IN.txcoord.xy, SamplerBloom3, 16, 0, 0);
	bloom.a *= fAnamFlareAmount;
	bloom.xyz *= fBloomAmount;
	return bloom;
}
float4 PS_ME_BloomPass4(VS_OUTPUT_POST IN) : COLOR
{
	float4 bloom;
	bloom.xyz = GaussBlur22(IN.txcoord.xy, SamplerBloom4, 16, 0, 1).xyz*2.5;	
	bloom.w   = GaussBlur22(IN.txcoord.xy, SamplerBloom4, 32*fAnamFlareWideness, 0, 0).w*2.5; //to have anamflare texture (bloom.w) avoid vertical blur
	return bloom;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Lensflares 													     	     //
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
float3 GetDnB (sampler2D tex, float2 coords)
{
	float3 Color = max(0,dot(tex2Dlod(tex,float4(coords.xy,0,4)).rgb,0.333) - ChapFlareTreshold)*ChapFlareIntensity;
	#if(CHAPMANDEPTHCHECK == 1)
	if(tex2Dlod(SamplerDepth,float4(coords.xy,0,3)).x<0.99999) Color = 0;
	#endif
	return Color;
}
float2 GetFlippedTC(float2 texcoords) 
{
	return -texcoords + 1.0;
}
float3 GetDistortedTex(
	sampler2D tex,
	float2 sample_center, // where we'd normally sample
	float2 sample_vector,
	float3 distortion // per-channel distortion coeffs
) {
	float2 final_vector = sample_center + sample_vector * min(min(distortion.r, distortion.g),distortion.b); 
	if(final_vector.x > 1.0 
	|| final_vector.y > 1.0 
	|| final_vector.x < -1.0 
	|| final_vector.y < -1.0)
	return 0;
	else return float3(
		GetDnB(tex,sample_center + sample_vector * distortion.r).r,
		GetDnB(tex,sample_center + sample_vector * distortion.g).g,
		GetDnB(tex,sample_center + sample_vector * distortion.b).b
	);
}
float3 GetBrightPass(float2 tex)
{
	float3 c = tex2D(SamplerHDR1, tex).rgb;
    	float3 bC = max(c - float3(fFlareLuminance, fFlareLuminance, fFlareLuminance), 0.0);
    	float bright = dot(bC, 1.0);
    	bright = smoothstep(0.0f, 0.5, bright);
	float3 result = lerp(0.0, c, bright);
#if (bFlareDepthCheckEnable == 1)
	float checkdepth = tex2D(SamplerDepth, tex).x;
	if(checkdepth < 0.99999) result = 0;
#endif
	return result;
}
float3 GetAnamorphicSample(int axis, float2 tex, float blur)
{
	tex = 2.0 * tex - 1.0;
	tex.x /= -blur;
	tex = 0.5 * tex + 0.5;
	return GetBrightPass(tex);
}
float4 PS_ME_LensPrepass(VS_OUTPUT_POST IN) : COLOR
{
	float4 lens=0;
#if (USE_LENZFLARE == 1)
	float3 lfoffset[19]={
		float3(0.9, 0.01, 4),
		float3(0.7, 0.25, 25),
		float3(0.3, 0.25, 15),
		float3(1, 1.0, 5),
		float3(-0.15, 20, 1),
		float3(-0.3, 20, 1),
		float3(6, 6, 6),
		float3(7, 7, 7),
		float3(8, 8, 8),
		float3(9, 9, 9),
		float3(0.24, 1, 10),
		float3(0.32, 1, 10),
		float3(0.4, 1, 10),
		float3(0.5, -0.5, 2),
		float3(2, 2, -5),
		float3(-5, 0.2, 0.2),
		float3(20, 0.5, 0),
		float3(0.4, 1, 10),
		float3(0.00001, 10, 20)
	};
	float3 lffactors[19]={
		float3(1.5, 1.5, 0),
		float3(0, 1.5, 0),
		float3(0, 0, 1.5),
		float3(0.2, 0.25, 0),
		float3(0.15, 0, 0),
		float3(0, 0, 0.15),
		float3(1.4, 0, 0),
		float3(1, 1, 0),
		float3(0, 1, 0),
		float3(0, 0, 1.4),
		float3(1, 0.3, 0),
		float3(1, 1, 0),
		float3(0, 2, 4),
		float3(0.2, 0.1, 0),
		float3(0, 0, 1),
		float3(1, 1, 0),
		float3(1, 1, 0),
		float3(0, 0, 0.2),
 	       	float3(0.012,0.313,0.588)
	};
	float3 lenstemp = 0;
	float2 lfcoord = float2(0,0);
	float2 distfact=(IN.txcoord.xy-0.5);
	distfact.x *= ScreenSize.z;
	for (int i=0; i<19; i++)
	{
		lfcoord.xy=lfoffset[i].x*distfact;
		lfcoord.xy*=pow(2.0*length(float2(distfact.x,distfact.y)), lfoffset[i].y*3.5);
		lfcoord.xy*=lfoffset[i].z;
		lfcoord.xy=0.5-lfcoord.xy;
		float2 tempfact = (lfcoord.xy-0.5)*2;
		float templensmult = clamp(1.0-dot(tempfact,tempfact),0,1);
		float3 lenstemp1 = dot(tex2Dlod(SamplerHDR1, float4(lfcoord.xy,0,1)).xyz,0.333);
		#if (LENZDEPTHCHECK == 1)
		float templensdepth = tex2D(SamplerDepth, lfcoord.xy).x;
		if(templensdepth < 0.99999) lenstemp1 = 0;
		#endif	
	
		lenstemp1 = max(0,lenstemp1.xyz - fLenzThreshold);
		lenstemp1 *= lffactors[i].xyz*templensmult;
		lenstemp += lenstemp1;
	}
	lens.xyz += lenstemp.xyz*fLenzIntensity;
#endif
#if(USE_CHAPMAN_LENS == 1)
	float2 sample_vector = (float2(0.5,0.5) - IN.txcoord.xy) * ChapFlareDispersal;
	float2 halo_vector = normalize(sample_vector) * ChapFlareSize;
	float3 chaplens = GetDistortedTex(SamplerHDR1, IN.txcoord.xy + halo_vector,halo_vector,ChapFlareCA*2.5f).rgb;
	for (int i = 0; i < ChapFlareCount; ++i) 
	{
		float2 foffset = sample_vector * float(i);
		chaplens += GetDistortedTex(SamplerHDR1, IN.txcoord.xy + foffset,foffset,ChapFlareCA).rgb;
	}
	chaplens *= 1/float(ChapFlareCount);
	lens.xyz += chaplens;
#endif
#if( USE_GODRAYS == 1)
	float2 ScreenLightPos = float2(0.5, 0.5);
	float2 texCoord = IN.txcoord.xy;
	float2 deltaTexCoord = (texCoord.xy - ScreenLightPos.xy);
	deltaTexCoord *= 1.0 / (float)iGodraySamples * fGodrayDensity;
	float illuminationDecay = 1.0;
	for(int g = 0; g < iGodraySamples; g++) {
	
		texCoord -= deltaTexCoord;;
		float4 sample2 = tex2D(SamplerHDR1, texCoord.xy);
		float sampledepth = tex2D(SamplerDepth, texCoord.xy).x;
		sample2.w = saturate(dot(sample2.xyz, 0.3333) - fGodrayThreshold);
		sample2.r *= 1.0;
		sample2.g *= 0.95;
		sample2.b *= 0.85;
		sample2 *= illuminationDecay * fGodrayWeight;
	#if (bGodrayDepthCheck == 1)
		if(sampledepth>0.99999) lens.xyz += sample2.xyz*sample2.w;
	#else
		lens.xyz += sample2;
	#endif
		illuminationDecay *= fGodrayDecay;
	}
#endif
#if(USE_ANAMFLARE == 1)
	float3 anamFlare=0;
	float gaussweight[5] = {0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162};
	for(int z=-4; z < 5; z++)
	{
		anamFlare+=GetAnamorphicSample(0, IN.txcoord.xy + float2(0, z * PixelSize.y * 2), fFlareBlur) * fFlareTint* gaussweight[abs(z)];
	}
	lens.xyz += anamFlare * fFlareIntensity;
#endif
	return lens;
}
float4 PS_ME_LensPass1(VS_OUTPUT_POST IN) : COLOR
{
	return GaussBlur22(IN.txcoord.xy, SamplerLens1, 2, 0, 1);	
}
float4 PS_ME_LensPass2(VS_OUTPUT_POST IN) : COLOR
{
	return GaussBlur22(IN.txcoord.xy, SamplerLens2, 2, 0, 0);	
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Lighting combine													     //
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
float4 PS_ME_LightingCombine(VS_OUTPUT_POST IN) : COLOR 
{
 
	float4 color = tex2D(SamplerHDR2, IN.txcoord.xy);
#if (USE_BLOOM == 1)
	float3 colorbloom=0;
	colorbloom.xyz += tex2D(SamplerBloom3, IN.txcoord.xy).xyz*1.0;
	colorbloom.xyz += tex2D(SamplerBloom5, IN.txcoord.xy).xyz*9.0;
	colorbloom.xyz *= 0.1;
	colorbloom.xyz = saturate(colorbloom.xyz);
	float colorbloomgray = dot(colorbloom.xyz, 0.333);
	colorbloom.xyz = lerp(colorbloomgray, colorbloom.xyz, fBloomSaturation);
	colorbloom.xyz *= fBloomTint;
	float colorgray = dot(color.xyz, 0.333);
	if(iBloomMixmode == 1) color.xyz = color.xyz + colorbloom.xyz;
	if(iBloomMixmode == 2) color.xyz = 1-(1-color.xyz)*(1-colorbloom.xyz);
	if(iBloomMixmode == 3) color.xyz = max(0.0f,max(color.xyz,lerp(color.xyz,(1.0f - (1.0f - saturate(colorbloom.xyz)) *(1.0f - saturate(colorbloom.xyz * 1.0))),1.0)));
	if(iBloomMixmode == 4) color.xyz = max(color.xyz, colorbloom.xyz);
#endif
#if(USE_GAUSSIAN_ANAMFLARE == 1)
	float3 anamflare = tex2D(SamplerBloom5, IN.txcoord.xy).w*2*fAnamFlareColor;
	anamflare.xyz = max(anamflare.xyz,0);
	color.xyz += pow(anamflare.xyz,1/fAnamFlareCurve);
#endif
#if(USE_LENSDIRT == 1)
	float lensdirtmult = dot(tex2D(SamplerBloom5, IN.txcoord.xy).xyz,0.333);
	float3 dirttex = tex2D(SamplerDirt, IN.txcoord.xy).xyz;
	float3 lensdirt = dirttex.xyz*lensdirtmult*fLensdirtIntensity*fLensdirtTint;
	lensdirt = lerp(dot(lensdirt.xyz,0.333), lensdirt.xyz, fLensdirtSaturation);
	if(iLensdirtMixmode == 1) color.xyz = color.xyz + lensdirt.xyz;
	if(iLensdirtMixmode == 2) color.xyz = 1-(1-color.xyz)*(1-lensdirt.xyz);
	if(iLensdirtMixmode == 3) color.xyz = max(0.0f,max(color.xyz,lerp(color.xyz,(1.0f - (1.0f - saturate(lensdirt.xyz)) *(1.0f - saturate(lensdirt.xyz * 1.0))),1.0)));
	if(iLensdirtMixmode == 4) color.xyz = max(color.xyz, lensdirt.xyz);
#endif
	float3 LensflareSample = tex2D(SamplerLens1, IN.txcoord.xy).xyz;
	float3 LensflareMask   = tex2D(SamplerSprite, IN.txcoord.xy+float2(0.5,0.5)*PixelSize.xy).xyz;
	LensflareMask   += tex2D(SamplerSprite, IN.txcoord.xy+float2(-0.5,0.5)*PixelSize.xy).xyz;
	LensflareMask   += tex2D(SamplerSprite, IN.txcoord.xy+float2(0.5,-0.5)*PixelSize.xy).xyz;
	LensflareMask   += tex2D(SamplerSprite, IN.txcoord.xy+float2(-0.5,-0.5)*PixelSize.xy).xyz;
	color.xyz += LensflareMask*0.25*LensflareSample;
	return color;
}
float4 PS_ME_Colors(VS_OUTPUT_POST IN) : COLOR 
{
	float4 color = tex2D(SamplerHDR1, IN.txcoord.xy);
#if(USE_LED_SHADER == 1 )
	float LEDradius = fLEDCircleSize * 0.375;
	float2 quadPos = floor(IN.txcoord.xy * float2(BUFFER_WIDTH,BUFFER_HEIGHT) / fLEDCircleSize) * fLEDCircleSize;
	float2 quad = quadPos/float2(BUFFER_WIDTH,BUFFER_HEIGHT);
	float2 quadCenter = (quadPos + fLEDCircleSize/2.0);
	float quaddist = length(quadCenter - IN.txcoord.xy * float2(BUFFER_WIDTH,BUFFER_HEIGHT));
	float4 LEDtexel = tex2D(SamplerHDR1, quad);
	float LEDtexellum = saturate(dot(LEDtexel.xyz,0.333)-0.75)*fLEDCircleSize*0.33;
	color.xyz = lerp(fLEDBackgroundColor, LEDtexel.xyz, smoothstep(1.5*(1.0+LEDtexellum),-1.5*(1.0+LEDtexellum), quaddist-LEDradius));
#endif	
#if(USE_LUT == 1)
	float3 LUTcolor = 0.0;	
 #if(iLookupTableMode == 1)  
	LUTcolor.x = tex2D(SamplerLUT, float2(saturate(color.x),0)).x;
	LUTcolor.y = tex2D(SamplerLUT, float2(saturate(color.y),0)).y;
	LUTcolor.z = tex2D(SamplerLUT, float2(saturate(color.z),0)).z;
 #elif (iLookupTableMode == 2)
	float2 GridSize = float2(0.00390625, 0.0625);
	float3 coord3D = saturate(color.xyz);
	coord3D.z  *= 15;
	float shift = floor(coord3D.z);
	coord3D.xy =  coord3D.xy * 15 * GridSize + 0.5 * GridSize;
	coord3D.x += shift * 0.0625;
	LUTcolor.xyz = lerp( tex2D(SamplerLUT3D, coord3D.xy).xyz, tex2D(SamplerLUT3D, coord3D.xy + float2(GridSize.y, 0)).xyz, coord3D.z - shift);
 #endif
	color.xyz = lerp(color.xyz, LUTcolor.xyz, fLookupTableMix);
#endif
#if (USE_CARTOON == 1)
	color.xyz = CartoonPass(color.xyz, IN.txcoord.xy, PixelSize.xy, SamplerHDR1);
#endif
#if (USE_LEVELS== 1)
	color.xyz = LevelsPass(color.xyz);
#endif
#if (USE_TECHNICOLOR == 1)
	color.xyz = TechniPass_prod80(color.xyz);
#endif
#if (USE_SWFX_TECHNICOLOR == 1)
	color.xyz = TechnicolorPass(color.xyz);
#endif
#if (USE_DPX == 1)
	color.xyz = DPXPass(color.xyz);
#endif
#if (USE_MONOCHROME == 1)
	color.xyz = dot(color.xyz, 0.333);
#endif
#if (USE_LIFTGAMMAGAIN == 1)
	color.xyz = LiftGammaGainPass(color.xyz);
#endif
	
#if (USE_TONEMAP == 1)
	color.xyz = TonemapPass(color.xyz);
#endif
	
#if (USE_VIBRANCE == 1)
	color.xyz = VibrancePass(color.xyz);
#endif
	
#if (USE_CURVES == 1)
	color.xyz = CurvesPass(color.xyz);
#endif
#if (USE_SEPIA == 1)
	color.xyz = SepiaPass(color.xyz);
#endif
#if (USE_SKYRIMTONEMAP == 1)
	color.xyz = SkyrimTonemapPass(color.xyz);
#endif
#if (USE_COLORMOOD == 1)
	color.xyz = MoodPass(color.xyz);
#endif
 
#if (USE_CROSSPROCESS == 1)
	color.xyz = CrossPass(color.xyz);
#endif
	
#if (USE_FILMICPASS == 1)
	color.xyz = FilmPass(color.xyz);
#endif
#if (USE_REINHARD == 1)
	color.xyz = ReinhardToneMapping(color.xyz);
#endif
#if (USE_REINHARDLINEAR == 1)
	color.xyz = ReinhardLinearToneMapping(color.xyz);
#endif
#if (USE_HPD == 1)
	color.xyz = HaarmPeterDuikerFilmicToneMapping(color.xyz);
#endif
	
#if (USE_FILMICCURVE == 1)
	color.xyz = CustomToneMapping(color.xyz);
#endif
#if(USE_WATCHDOG_TONEMAP == 1)
	color.xyz = ColorFilmicToneMapping(color.xyz);
#endif
#if (USE_COLORMOD == 1)
	color.xyz = ColormodPass(color.xyz);
#endif
#if (USE_SPHERICALTONEMAP == 1)
	color.xyz = SphericalPass(color.xyz);
#endif
#if (USE_SINCITY == 1)
	color.xyz = SincityPass(color.xyz);
#endif
#if (USE_COLORHUEFX == 1)
	color.xyz = colorhuefx_prod80(color.xyz);
#endif
	return color;
}
float4 PS_ME_PostFX(VS_OUTPUT_POST IN) : COLOR 
{
#if (USE_SMAA == 1)
 #define SamplerCurrent SamplerHDR1
#else
 #define SamplerCurrent SamplerHDR2
#endif
	float4 color = tex2D(SamplerCurrent, IN.txcoord.xy);
#if(USE_FISHEYE_CA == 1)
	float4 coord=0.0;
	coord.xy=IN.txcoord.xy;
	coord.w=0.0;  
	float3 eta = float3(1.0+fFisheyeColorshift*0.9,1.0+fFisheyeColorshift*0.6,1.0+fFisheyeColorshift*0.3);
	float2 center;
	center.x = coord.x-0.5;
	center.y = coord.y-0.5;
	float LensZoom = 1.0/fFisheyeZoom;
	float r2 = (IN.txcoord.x-0.5) * (IN.txcoord.x-0.5) + (IN.txcoord.y-0.5) * (IN.txcoord.y-0.5);     
	float f = 0;
	if( fFisheyeDistortionCubic == 0.0){
		f = 1 + r2 * fFisheyeDistortion;
	}else{
                f = 1 + r2 * (fFisheyeDistortion + fFisheyeDistortionCubic * sqrt(r2));
	};
	float x = f*LensZoom*(coord.x-0.5)+0.5;
	float y = f*LensZoom*(coord.y-0.5)+0.5;
	float2 rCoords = (f*eta.r)*LensZoom*(center.xy*0.5)+0.5;
	float2 gCoords = (f*eta.g)*LensZoom*(center.xy*0.5)+0.5;
	float2 bCoords = (f*eta.b)*LensZoom*(center.xy*0.5)+0.5;
	
	color.x = tex2D(SamplerCurrent,rCoords).r;
	color.y = tex2D(SamplerCurrent,gCoords).g;
	color.z = tex2D(SamplerCurrent,bCoords).b;	
#endif
#undef SamplerCurrent
	return color;
}
float4 PS_ME_Overlay(VS_OUTPUT_POST IN) : COLOR 
{
#if (USE_SMAA == 1)
 #define SamplerCurrent SamplerHDR2
#else
 #define SamplerCurrent SamplerHDR1
#endif
	float4 color = tex2D(SamplerCurrent, IN.txcoord.xy);
#if( USE_HEATHAZE == 1)
	float3 heatnormal = tex2Dlod(SamplerHeat, float4(IN.txcoord.xy*fHeatHazeTextureScale+float2(0.0,Timer.x*0.0001*fHeatHazeSpeed),0,0)).rgb - 0.5;
    	float2 heatoffset = normalize(heatnormal.xy) * pow(length(heatnormal.xy), 0.5);
	float3 heathazecolor = 0;
	heathazecolor.y = tex2D(SamplerCurrent, IN.txcoord.xy + heatoffset.xy * 0.001 * fHeatHazeOffset).y;
	heathazecolor.x = tex2D(SamplerCurrent, IN.txcoord.xy + heatoffset.xy * 0.001 * fHeatHazeOffset * (1.0+fHeatHazeChromaAmount)).x;
	heathazecolor.z = tex2D(SamplerCurrent, IN.txcoord.xy + heatoffset.xy * 0.001 * fHeatHazeOffset * (1.0-fHeatHazeChromaAmount)).z;
	color.xyz = heathazecolor;
 #if(bHeatHazeDebug == 1)
	color.xyz = heatnormal.xyz+0.5;
 #endif
#endif
/*   xyz
Must be moved elsewhere in order to be used correctly.
Reminder to me: Enable CoC for FOG, too.
#define USE_FOG 1
#define fFogStart 	 0.1
#define	fFogEnd 	 0.7
#define	fFogAmount   	 1.0
#define fFogColor	float3(0.67,0.67,0.67)
#if( USE_FOG == 1)
	float lineardepth = tex2Dlod(SamplerCoC, float4(IN.txcoord.xy,0,0)).y;
	float fogdepth=0;
	fogdepth += tex2Dlod(SamplerCoC, float4(IN.txcoord.xy,0,2)).y;
	fogdepth += tex2Dlod(SamplerCoC, float4(IN.txcoord.xy,0,3)).y;
	fogdepth += tex2Dlod(SamplerCoC, float4(IN.txcoord.xy,0,4)).y;
	fogdepth /= 3;
	fogdepth = lerp(lineardepth, fogdepth, saturate(lineardepth*3));
	float fogamount = saturate(smoothstep(fFogStart, fFogEnd, fogdepth)*fFogAmount);
	float3 fogblur=0;
	fogblur += tex2Dlod(SamplerCurrent, float4(IN.txcoord.xy,0,2)).xyz;
	fogblur += tex2Dlod(SamplerCurrent, float4(IN.txcoord.xy,0,3)).xyz;
	fogblur += tex2Dlod(SamplerCurrent, float4(IN.txcoord.xy,0,4)).xyz;
	fogblur /= 3;
	float3 fogcolor = fFogColor;
	fogblur = (fogblur - fogcolor) * 0.75 + fogcolor;
	color.xyz = lerp(color.xyz, fogblur, saturate(fogamount*2));
	color.xyz = lerp(color.xyz, fogcolor, fogamount);
#endif
*/
#if(USE_SHARPENING == 1)
	color.xyz = SharpPass(color.xyz, IN.txcoord.xy, SamplerCurrent);
#endif
#if (USE_EXPLOSION == 1)
	color.xyz = ExplosionPass(color.xyz, IN.txcoord.xy, SamplerCurrent);
#endif
#if(USE_GRAIN == 1)
	float3 noisesample = tex2D(SamplerNoise, IN.txcoord.xy).xyz;
	float noisegray = dot(noisesample, 0.333);
	noisesample.xyz = lerp(noisegray.xxx, noisesample.xyz, fGrainSaturation);
	float colorgray = dot(color.xyz, 0.333);
	float fGrainAmount = fGrainIntensityMid;
	if(colorgray > 0.5) fGrainAmount = lerp(fGrainIntensityMid, fGrainIntensityBright, saturate(colorgray-0.5)*2);
	if(colorgray < 0.5) fGrainAmount = lerp(fGrainIntensityDark, fGrainIntensityMid, colorgray*2);
	noisesample.xyz = (noisesample.xyz-0.5)*fGrainAmount;
	color.xyz = max(0, color.xyz + noisesample.xyz);
#endif
#if (USE_COLORVIGNETTE==1)
        float2	uv=(IN.txcoord-0.5)*fVignetteRadius;
	float	vignetteold=saturate(dot(uv.xy, uv.xy));
	vignetteold=pow(vignetteold, fVignetteCurve);
	float3	EVignetteColor=fVignetteColor;
	color.xyz=lerp(color.xyz, EVignetteColor, vignetteold*fVignetteAmount);
#endif
#if (USE_HD6_VIGNETTE==1)
	float rovigpwr = fHD6VignetteRoundness; //for a circular vignette
	float2 sqvigpwr = float2( fHD6VignetteTop, fHD6VignetteBottom ); // for the top and bottom of the screen
	float vsatstrength = fHD6VignetteColorDistort; // color distortion
	float vignettepow = fHD6VignetteContrast; // increases the contrast and sharpness
	float vstrengthatnight = fHD6VignetteBorder;
 
 	float2 inTex = IN.txcoord;
 	float vhnd = 0.5;
 	float4 voriginal = color;
 	float4 vcolor = voriginal;
 	vcolor.xyz=1;
 	inTex -= 0.5; // center
 	inTex.y += 0.01; // offset from the center
 	float vignette = saturate(1.0 - dot( inTex, inTex ));
 	vcolor *= pow( vignette, vignettepow );
 
 	float4 rvigtex = vcolor;
 	rvigtex.xyz = pow( vcolor.xyz, 1 );
 	rvigtex.xyz = lerp(float3(0.5, 0.5, 0.5), rvigtex.xyz, 2.25); // contrast
 	rvigtex.xyz = lerp(float3(1,1,1),rvigtex.xyz,rovigpwr); // strength of the circular vinetty
 
	//darken the top and bottom
 	float4 vigtex = vcolor;
 	vcolor.xyz = float3(1,1,1);
 #if (fHD6VignetteMode==1)
 	float3 topv = min((inTex.x+0.5)*2,1.5) * 2; // top
 	float3 botv = min(((0-inTex.x)+0.5)*2,1.5) * 2; // botton
	topv= lerp(float3(1,1,1), topv, sqvigpwr.x);
 	botv= lerp(float3(1,1,1), botv, sqvigpwr.y);
	vigtex.xyz = (topv)*(botv);
 #endif
 #if (fHD6VignetteMode==2)
        float3 topv = min((inTex.y+0.5)*2,1.5) * 2; // top
 	float3 botv = min(((0-inTex.y)+0.5)*2,1.5) * 2; // botton
	topv= lerp(float3(1,1,1), topv, sqvigpwr.x);
 	botv= lerp(float3(1,1,1), botv, sqvigpwr.y);
	vigtex.xyz = (topv)*(botv);
 #endif
 #if (fHD6VignetteMode==3)
	float3 rightv = min((inTex.x+0.5)*2,1.5) * 2;
 	float3 leftv = min(((0-inTex.x)+0.5)*2,1.5) * 2; 
        float3 topv = min((inTex.y+0.5)*2,1.5) * 2; 
 	float3 botv = min(((0-inTex.y)+0.5)*2,1.5) * 2; 
 	rightv= lerp(float3(1,1,1), rightv, sqvigpwr.y);
 	leftv= lerp(float3(1,1,1), leftv, sqvigpwr.x);
        topv= lerp(float3(1,1,1), topv, sqvigpwr.x);
 	botv= lerp(float3(1,1,1), botv, sqvigpwr.y);
 	vigtex.xyz = (topv)*(botv)*(rightv)*(leftv);
 #endif
 	// mix the two types of vignettes
 	vigtex.xyz*=rvigtex.xyz;
	vigtex.xyz = lerp(vigtex.xyz,float3(1,1,1),(vhnd-vstrengthatnight*vhnd)); //for a dark screen
 	vigtex.xyz = min(vigtex.xyz,1);
 	vigtex.xyz = max(vigtex.xyz,0);
 	float3 vtintensity = dot(voriginal.xyz, float3(0.2125, 0.7154, 0.0721));
 	color.xyz = lerp(vtintensity, voriginal.xyz, ((((1-(vigtex.xyz*2))+2)-1)*vsatstrength)+1 );
  	color.xyz *= (vigtex.xyz);
#endif
#if (USE_BORDER==1)
	color.xyz = BorderPass(color, IN.txcoord.xy).xyz;
#endif
#if (USE_MOVIEBARS == 1)
	color.xyz = IN.txcoord.y > 0.12 && IN.txcoord.y < 0.88 ? color.xyz : 0.0;
#endif
#if(USE_DEPTHBUFFER_OUTPUT == 1)
	color.xyz = GetLinearDepth(tex2D(SamplerDepth, IN.txcoord.xy).x);
#endif
#if(USE_SPLITSCREEN == 1)
	if(IN.txcoord.x > 0.5) color.xyz = tex2D(SamplerLDR, IN.txcoord.xy).xyz;
#endif
#if(USE_HUD_MASKING == 1)
	float HUDMaskSample = tex2D(SamplerMask, IN.txcoord.xy).x;
	float3 origcolor = tex2D(SamplerLDR, IN.txcoord.xy).xyz;
	color.xyz = lerp(origcolor.xyz, color.xyz, saturate(HUDMaskSample));
#endif
	return color;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
technique MasterEffect < bool enabled = 1; toggle = MASTEREFFECT_TOGGLEKEY; >
{
	pass ME_Init
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_Init;
		RenderTarget = texHDR1;
	}
								//so both HDR1 and HDR2 textures are filled with input color
	pass ME_Init						//later, numerous DOF shaders have different passnumber but later passes depend
	{							//on fixed HDR1 HDR2 HDR1 HDR2... sequence so a 2 pass DOF outputs HDR1 in pass 1 and 	
		VertexShader = VS_MasterEffect;			//HDR2 in second pass, a 3 pass DOF outputs HDR2, HDR1, HDR2 so last pass outputs always HDR2
		PixelShader = PS_ME_Init;
		RenderTarget = texHDR2;
	}
#if(USE_AMBIENTOCCLUSION == 1)
  #if(AO_METHOD==1)
	pass ME_SSAO
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_SSAO;
		RenderTarget = texOcclusion1;
	}
  #endif
  #if(AO_METHOD==2)
	pass ME_RayAO
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_RayAO;
		RenderTarget = texOcclusion1;
	}
  #endif
  #if(AO_METHOD==3)
	pass ME_HBAO
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_HBAO;
		RenderTarget = texOcclusion1;
	}
  #endif
  #if(AO_METHOD==5)
	pass ME_HBAO
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_RayHBAO;
		RenderTarget = texOcclusion1;
	}
  #endif
  #if(AO_METHOD==6)
	pass ME_HBAO
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_SAO;
		RenderTarget = texOcclusion1;
	}
  #endif
  #if(AO_METHOD != 4)
	pass ME_AOBlurV
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_AOBlurV;
		RenderTarget = texOcclusion2;
	}
	
	pass ME_AOBlurH
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_AOBlurH;
		RenderTarget = texOcclusion1;
	}
	pass ME_AOCombine
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_AOCombine;
		RenderTarget = texHDR2; 
	}	
  #endif
  #if(AO_METHOD == 4)
	pass ME_SSGI
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_SSGI;
		RenderTarget = texOcclusion1;
	}
	pass ME_GIBlurV
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_GIBlurV;
		RenderTarget = texOcclusion2;
	}
	pass ME_GIBlurH
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_GIBlurH;
		RenderTarget = texOcclusion1;
	}
	pass ME_GICombine
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_GICombine;
		RenderTarget = texHDR2; 
	}
  #endif
#endif
#if (USE_BLOOM == 1 || USE_GAUSSIAN_ANAMFLARE == 1 || USE_LENSDIRT == 1)
	pass BloomPrePass
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_BloomPrePass;
		RenderTarget = texBloom1;
	}
	
	pass BloomPass1
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_BloomPass1;
		RenderTarget = texBloom2;
	}
	pass BloomPass2
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_BloomPass2;
		RenderTarget = texBloom3;
	}
	pass BloomPass3
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_BloomPass3;
		RenderTarget = texBloom4;
	}
	pass BloomPass4
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_BloomPass4;
		RenderTarget = texBloom5;
	}
#endif
#if (USE_LENZFLARE == 1 || USE_CHAPMAN_LENS == 1 || USE_GODRAYS == 1 || USE_ANAMFLARE == 1)
	pass ME_LensPrepass
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_LensPrepass;
		RenderTarget = texLens1;
	}
	
	pass ME_LensPass1
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_LensPass1;
		RenderTarget = texLens2;
	}
	pass ME_LensPass2
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_LensPass2;
		RenderTarget = texLens1;
	}
#endif
#if(USE_DEPTHOFFIELD == 1)
	pass ME_CoC
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_CoC;
		RenderTarget = texCoC;
	}
#endif
#if(USE_DEPTHOFFIELD==1)
   #if(DOF_METHOD==1)	
	pass ME_RingDOF1
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_RingDOF1;
		RenderTarget = texHDR1;
	}
	pass ME_RingDOF2
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_RingDOF2;
		RenderTarget = texHDR2;
	}
   #endif
   #if(DOF_METHOD==2)	
	pass ME_MagicDOF1
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_MagicDOF1;
		RenderTarget = texHDR1;
	}
	pass ME_MagicDOF2
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_MagicDOF2;
		RenderTarget = texHDR2;
	}
   #endif
   #if(DOF_METHOD==3)	
	pass ME_GPDOF1
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_GPDOF1;
		RenderTarget = texHDR1;
	}
	pass ME_GPDOF2
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_GPDOF2;
		RenderTarget = texHDR2;
	}
   #endif
   #if(DOF_METHOD==4)	
	pass ME_MatsoDOF1
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_MatsoDOF1;
		RenderTarget = texHDR1;
	}
	pass ME_MatsoDOF2
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_MatsoDOF2;
		RenderTarget = texHDR2;
	}
	pass ME_MatsoDOF3
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_MatsoDOF3;
		RenderTarget = texHDR1;
	}
	pass ME_MatsoDOF4
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_MatsoDOF4;
		RenderTarget = texHDR2;
	}
   #endif
#endif
	pass ME_LightingCombine
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_LightingCombine;
		RenderTarget = texHDR1;
	}
	pass ME_Colors
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_Colors;
		RenderTarget = texHDR2;
	}
#if (USE_SMAA == 1)
	pass SMAA_EdgeDetection //First SMAA Pass
	{
		VertexShader = SMAAEdgeDetectionVSWrap;
 #if (iSMAAEdgeDetectionMode == 1)
		PixelShader = SMAALumaEdgeDetectionPSWrap;
 #elif (iSMAAEdgeDetectionMode == 3)
		PixelShader = SMAADepthEdgeDetectionPSWrap;
 #else
		PixelShader = SMAAColorEdgeDetectionPSWrap; //Probably the best in most cases so I default to this.
 #endif
		StencilEnable = true;
		StencilPass = REPLACE;
		StencilRef = 1;
		RenderTarget = texEdges;
	}
	
	pass SMAA_BlendWeightCalculation //Second SMAA Pass
	{
		VertexShader = SMAABlendingWeightCalculationVSWrap;
		PixelShader = SMAABlendingWeightCalculationPSWrap;
     		StencilEnable = true;
		StencilPass = KEEP;
		StencilFunc = EQUAL;
		StencilRef = 1;
		RenderTarget = texBlend;
	}
	
	pass SMAA_NeighborhoodBlending //Third SMAA Pass
	{
		VertexShader = SMAANeighborhoodBlendingVSWrap;
		PixelShader  = SMAANeighborhoodBlendingPSWrap;
		
 #if (iSMAADebugOutput == 5)
		// Use the stencil so we can show it.
		StencilEnable = true;
		StencilPass = KEEP;
		StencilFunc = EQUAL;
		StencilRef = 1;
 #else
		// Process all the pixels.
		StencilEnable = false;
 #endif
		RenderTarget = texHDR1;	
	}
#endif
	pass ME_PostFX
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_PostFX;
#if (USE_SMAA == 1)					//exactly what I wanted to prevent with new system :(
		RenderTarget = texHDR2;			//but I see now, first AA and then chromatic abberation gives smoother result...
#else							//this of course eliminates the option to use 2 AA's together because with each count 
		RenderTarget = texHDR1;			//this here would get more and more complicated...damn
#endif							//Noone will ever read this so I'm basically talking to a text file. Hello text file.
	}						
	pass ME_Overlay
	{
		VertexShader = VS_MasterEffect;
		PixelShader = PS_ME_Overlay;
	}
}
     
    
I have added another step to the installation to fix the 'RFX_Depth_z_far' error that many people were having. I was unaware that the latest version of ReShade didn't have the variable declaration in it for all the depth variables (even though they are not used) and I have added a copy of the updated file to fix this issue. Sorry for the long wait as I don't have as much time to check up on this page very often.
I get the same error. C:\Games\Guild Wars 2\bin64\ReShade.fx(81, 28): error X3004: undeclared identifier 'RFX_Depth_z_far'
A fix would be nice. Thank you.
when starting the game , i get this error
C:\Games\Guild Wars 2\bin64\ReShade.fx(81, 28): error X3004: undeclared identifier 'RFX_Depth_z_far'