//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//http://enbdev.com
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
THIS IS HLSL FILE FORMAT FOR EXECUTING ADDITIONAL
POST PROCESSING EFFECTS. MAKE THE COPY BEFORE CHANGING IT!
*/

//enable sharpening
#define ESHARPENING

//if defined, color sharpen, otherwise sharp by gray
#define ESHARPENINGCOLOR

//enable noise in dark areas
//#define ENOISE

float ShiftSamplingRange=0.3;
float SamplingRange=0.8; //sharpening or blurring range
float SharpeningAmount=1.5;
float ScanLineAmount=3;
float ScanLineRepeat=0; //0.5, 0.3333, 0.25, 0.125, so on
float NoiseAmount=1.0;


//keyboard controled variables
float tempF1;
float tempF2;
float tempF3;
float tempF4;
float tempF5;
float tempF6;
float tempF7;
float tempF8;
float tempF9;
float tempF0;

//global variables, already set before executing this code
float ScreenSize; //width of the display resolution (1920 f.e.)
float ScreenScaleY; //screen proportions (1.333 for 1920/1080)

//textures
texture2D texColor;
texture2D texNoise;

sampler2D SamplerColor = sampler_state
{
	Texture   = <texColor>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;//NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerNoise = sampler_state
{
	Texture   = <texNoise>;
	MinFilter = POINT;
	MagFilter = POINT;
	MipFilter = NONE;//NONE;
	AddressU  = Wrap;
	AddressV  = Wrap;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

struct VS_OUTPUT_POST {
	float4 vpos  : POSITION;
	float2 txcoord : TEXCOORD0;
};

struct VS_INPUT_POST {
	float3 pos  : POSITION;
	float2 txcoord : TEXCOORD0;
};

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
VS_OUTPUT_POST VS_PostProcess(VS_INPUT_POST IN)
{
	VS_OUTPUT_POST OUT;

	float4 pos=float4(IN.pos.x,IN.pos.y,IN.pos.z,1.0);

	OUT.vpos=pos;
	OUT.txcoord.xy=IN.txcoord.xy;

	return OUT;
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//--------------------Fast Approximate Anti-Aliasing --------------------------
//         FXAA v2 CONSOLE by TIMOTHY LOTTES @ NVIDIA   
//          Ported to ENBSeries by MysTer92 (Svyatoslav Gampel)
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



float4 PS_PostProcess(VS_OUTPUT_POST i) : COLOR
{
	#define FXAA_SUBPIX_SHIFT (1.0/8.0)
	#define FXAA_REDUCE_MIN   (1.0/32.0)
	#define FXAA_REDUCE_MUL   (1.0/16.0)
	#define FXAA_SPAN_MAX     8.0

	half2 rcpFrame = half2(1/ScreenSize, 1/(ScreenSize/ScreenScaleY));

	half4 posPos;
	posPos.xy = i.txcoord.xy;
	posPos.zw = posPos.xy - (rcpFrame.xy * (0.5 + FXAA_SUBPIX_SHIFT));

	half3 rgbNW = tex2D(SamplerColor, posPos.zw ).xyz;
	half3 rgbNE = tex2D(SamplerColor, posPos.zw + half2(rcpFrame.x, 0.0) ).xyz;
	half3 rgbSW = tex2D(SamplerColor, posPos.zw + half2(0.0, rcpFrame.y) ).xyz;
	half3 rgbSE = tex2D(SamplerColor, posPos.zw +rcpFrame.xy ).xyz;
	half3 rgbM  = tex2D(SamplerColor, posPos.xy).xyz;
       
	half3 luma = half3(0.299, 0.587, 0.114);
	half lumaNW = dot(rgbNW, luma);
	half lumaNE = dot(rgbNE, luma);
	half lumaSW = dot(rgbSW, luma);
	half lumaSE = dot(rgbSE, luma);
	half lumaM  = dot(rgbM,  luma);
       
	half lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
	half lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
       
	half2 dir; 
       
	half lumaNWNE = lumaNW + lumaNE;
	half lumaSWSE = lumaSW + lumaSE;
       
	dir.x = -((lumaNWNE) - (lumaSWSE));
	dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));
       
	half dirReduce = max( (lumaSWSE + lumaNWNE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);
	half rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);
	dir = min(half2( FXAA_SPAN_MAX,  FXAA_SPAN_MAX), max(half2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * rcpFrame.xy;
             
	half3 rgbA = (1.0/2.0) * (tex2D(SamplerColor, posPos.xy + dir * (1.0/3.0 - 0.5) ).xyz + tex2D(SamplerColor, posPos.xy + dir * (2.0/3.0 - 0.5) ).xyz);
	half3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (tex2D(SamplerColor, posPos.xy + dir * (0.0/3.0 - 0.5) ).xyz + tex2D(SamplerColor, posPos.xy + dir * (3.0/3.0 - 0.5) ).xyz);
	half lumaB = dot(rgbB, luma);
     
	if((lumaB < lumaMin) || (lumaB > lumaMax))
 		return half4(rgbA, 1.0);
       
	return float4(rgbB, 1.0);
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//--------------------ENBSERIES SHARP & NOISE --------------------------
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

float4 PS_PostProcess_Sharp_Noise(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
	float4 res;
	float4 coord=0.0;

	coord.xy=IN.txcoord.xy;
	float4 origcolor;

	coord.w=0.0;

	origcolor=tex2Dlod(SamplerColor, coord);


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

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

	float4 tcol=origcolor;
	float invscreensize=1.0/ScreenSize;
	for (i=0; i<8; i++) //higher quality
	{
		float2 tdir=offset[i].xy;
		coord.xy=IN.txcoord.xy+tdir.xy*invscreensize*SamplingRange;//*1.0;
		float4 ct=tex2Dlod(SamplerColor, coord);

		tcol+=ct;
	}
	tcol*=0.131; // 1.0/(8+1)  //higher quality


	//sharp
	#ifdef ESHARPENING

	#ifdef ESHARPENINGCOLOR
	//color
	res=origcolor*(1.0+((origcolor-tcol)*SharpeningAmount));
	#else
	//non color
	float difffact=dot((origcolor.xyz-tcol.xyz), 0.333);
	res=origcolor*(10.0+difffact*SharpeningAmount);
	#endif

	//less sharpening for bright pixels
	float rgray=origcolor.z; //blue fit well
	//float rgray=max(origcolor.x, max(origcolor.y, origcolor.z));
	rgray=pow(rgray, 3.0);
	res=lerp(res, origcolor, saturate(rgray));

	#endif


	//grain noise
	#ifdef ENOISE
	float origgray=max(res.x, res.y);//dot(res.xyz, 0.333);
	origgray=max(origgray, res.z);
	coord.xy=IN.txcoord.xy*16.0 + origgray;
	float4 cnoi=tex2Dlod(SamplerNoise, coord);
	res=lerp(res, (cnoi.x+0.5)*res, NoiseAmount*saturate(1.0-origgray*1.8));
	#endif


	res.w=1.0;
	return res;
}


//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//--------------------Fast Approximate Anti-Aliasing Techniques -------------
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

technique PostProcess //FXAA
{
   pass P0
   {
	VertexShader = compile vs_3_0 VS_PostProcess();
	PixelShader  = compile ps_3_0 PS_PostProcess();

	FogEnable=FALSE;
	ALPHATESTENABLE=FALSE;
	SEPARATEALPHABLENDENABLE=FALSE;
	AlphaBlendEnable=FALSE;
	FogEnable=FALSE;
	SRGBWRITEENABLE=FALSE;
   }
}

technique PostProcess2 //FXAA
{
   pass P0
   {
	VertexShader = compile vs_3_0 VS_PostProcess();
	PixelShader  = compile ps_3_0 PS_PostProcess();

	FogEnable=FALSE;
	ALPHATESTENABLE=FALSE;
	SEPARATEALPHABLENDENABLE=FALSE;
	AlphaBlendEnable=FALSE;
	FogEnable=FALSE;
	SRGBWRITEENABLE=FALSE;
   }
}

technique PostProcess3 //FXAA
{
   pass P0
   {
	VertexShader = compile vs_3_0 VS_PostProcess();
	PixelShader  = compile ps_3_0 PS_PostProcess();

	FogEnable=FALSE;
	ALPHATESTENABLE=FALSE;
	SEPARATEALPHABLENDENABLE=FALSE;
	AlphaBlendEnable=FALSE;
	FogEnable=FALSE;
	SRGBWRITEENABLE=FALSE;
   }
}

technique PostProcess4 //FXAA
{
   pass P0
   {
	VertexShader = compile vs_3_0 VS_PostProcess();
	PixelShader  = compile ps_3_0 PS_PostProcess();

	FogEnable=FALSE;
	ALPHATESTENABLE=FALSE;
	SEPARATEALPHABLENDENABLE=FALSE;
	AlphaBlendEnable=FALSE;
	FogEnable=FALSE;
	SRGBWRITEENABLE=FALSE;
   }
}

technique PostProcess5
{
  pass P0
  {
	VertexShader = compile vs_3_0 VS_PostProcess();
	PixelShader  = compile ps_3_0 PS_PostProcess_Sharp_Noise();

	DitherEnable=TRUE;
	ZEnable=FALSE;
	CullMode=NONE;
	ALPHATESTENABLE=FALSE;
	SEPARATEALPHABLENDENABLE=FALSE;
	AlphaBlendEnable=FALSE;
	StencilEnable=FALSE;
	FogEnable=FALSE;
	SRGBWRITEENABLE=FALSE;
  }
}
