//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ENBSeries effect file
// visit http://enbdev.com for updates
// Copyright (c) 2007-2011 Boris Vorontsov
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Jasmin mod v3.6
//+++++++++++++++++++++++++++++
//internal parameters, can be modified
//+++++++++++++++++++++++++++++
float	EBlurSamplingRange=1.0;		// not used
float	EApertureScale=0.004;		// not used

//+++++++++++++++++++++++++++++
//external parameters, do not modify
//+++++++++++++++++++++++++++++
//keyboard controlled temporary variables (in some versions exists in the config file). Press and hold key 1,2,3...8 together with PageUp or PageDown to modify. By default all set to 1.0
float4	tempF1; //0,1,2,3
float4	tempF2; //5,6,7,8
float4	tempF3; //9,0
//x=Width, y=1/Width, z=ScreenScaleY, w=1/ScreenScaleY
float4	ScreenSize;
//x=generic timer in range 0..1, period of 16777216 ms (4.6 hours), w=frame time elapsed (in seconds)
float4	Timer;
//adaptation delta time for focusing
float	FadeFactor;

//textures
texture2D texColor;
texture2D texDepth;
texture2D texNoise;
texture2D texPalette;
texture2D texFocus; //computed focusing depth
texture2D texCurr; //4*4 texture for focusing
texture2D texPrev; //4*4 texture for focusing

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

sampler2D SamplerDepth = sampler_state
{
	Texture   = <texDepth>;
	MinFilter = POINT;
	MagFilter = POINT;
	MipFilter = 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;
};

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

//for focus computation
sampler2D SamplerCurr = sampler_state
{
	Texture   = <texCurr>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;//NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

//for focus computation
sampler2D SamplerPrev = sampler_state
{
	Texture   = <texPrev>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};
//for dof only in PostProcess techniques
sampler2D SamplerFocus = sampler_state
{
	Texture   = <texFocus>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	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;
};

////////////////////////////////////////////////////////////////////
//begin focusing code (by Boris Vorontsov)
////////////////////////////////////////////////////////////////////
VS_OUTPUT_POST VS_Focus(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;
}

//SRCpass1X=ScreenWidth;
//SRCpass1Y=ScreenHeight;
//DESTpass2X=4;
//DESTpass2Y=4;
float4 PS_ReadFocus(VS_OUTPUT_POST IN) : COLOR
{
	float2 uvsrc=IN.txcoord.xy;

	const float2 offset[4]=
	{
		float2(0.0, 0.3),
		float2(0.0, -0.3),
		float2(0.3, 0.0),
		float2(-0.3, 0.0)
	};

	float res = tex2D(SamplerDepth, uvsrc).x;
	for (int i = 0; i < 4; i++)
	{
		uvsrc.xy = offset[i];
		uvsrc.xy += IN.txcoord;
		res += tex2D(SamplerDepth, uvsrc).x;
	}
	res*=0.2;

	return res;
}

//SRCpass1X=4;
//SRCpass1Y=4;
//DESTpass2X=4;
//DESTpass2Y=4;
float4 PS_WriteFocus(VS_OUTPUT_POST IN) : COLOR
{
	float2 uvsrc=0.0;
	float	pos=0.0001;
	float	res=0.0;
	float	curr=0.0;
	float	prev=0.0;
	float	currmax=0.0;
	float	prevmax=0.0;
	for (int ix = 0; ix < 16; ix++)
	{
		float	tcurr=tex2D(SamplerCurr, (uvsrc.xy*0.25+0.125)).x;//the same for all 4 pixels
		float	tprev=tex2D(SamplerPrev, (uvsrc.xy*0.25+0.125)).x;//the same for all 4 pixels
		currmax=max(currmax, tcurr);
		prevmax=max(prevmax, tprev);
		curr+=tcurr;
		prev+=tprev;
		uvsrc.x+=1.0;
		if (uvsrc.x>4.0)
		{
			uvsrc.x=0.0;
			uvsrc.y+=1.0;
		}
	}
	curr*=0.0625;
	prev*=0.0625;

	res=lerp(prev, curr, saturate(FadeFactor));//time elapsed factor
	res=max(res, 0.0);

	return res;
}

technique ReadFocus
{
	pass P0
	{
		VertexShader = compile vs_3_0 VS_Focus();
		PixelShader  = compile ps_3_0 PS_ReadFocus();

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

technique WriteFocus
{
	pass P0
	{
		VertexShader = compile vs_3_0 VS_Focus();
		PixelShader  = compile ps_3_0 PS_WriteFocus();

		ZEnable=FALSE;
		CullMode=NONE;
		ALPHATESTENABLE=FALSE;
		SEPARATEALPHABLENDENABLE=FALSE;
		AlphaBlendEnable=FALSE;
		FogEnable=FALSE;
		SRGBWRITEENABLE=FALSE;
	}
}
////////////////////////////////////////////////////////////////////
//end focusing code
////////////////////////////////////////////////////////////////////

/*------------------------------------------------------------------------------
					Cinematic Setting 2.0.2 by Matso
					   Credits to Boris Vorontsov
			    
				 Depth of field with chromatic aberration
					 and sharpening effects applied.
------------------------------------------------------------------------------*/
// Effects enabling options
#define ENABLE_DOF		1			// comment to disable DoF
#define ENABLE_SHARP	1			// comment to disable sharpening

// Methods enabling options
#define USE_CHROMA		1			// comment it to disable chromatic aberration sampling
#define USE_SMOOTH_DOF	1			// comment it to disable smooth DoF
//#define USE_GRAIN		1			// comment it to disable movie grain
//#define USE_ANAMFLARE	1			// comment it to disable anamorphic lens flare (not working very well -_-)

// Useful constants
#define SEED			Timer.x + Timer.y + Timer.z
#define PI				3.1415926535897932384626433832795

// Chromatic aberration parameters
float3 fvChroma = float3(1.003, 1.003, 0.995);	// displacement scales of red, green and blue respectively
float fBaseRadius = 0.1;						// below this radius the effect is less visible
float fFalloffRadius = 38.0;						// over this radius the effects is maximal
float fChromaPower = 1.15;						// power of the effect (artifact - causes the whole image to get brighter or dimmer)
float fFocusScale = 2.0;						// power of chromatic aberration of distant objects (high values cause an artifact to appear on the image edges)

// Sharpen parameters
float fSharpScale = 0.05;						// intensity of sharpening
float2 fvTexelSize = float2(1.2 / 1222.0, 1.2 / 1222.0);	// set your resolution sizes

// Depth of field parameters
float fFocusBias = 0.01;						// high values cause the image to be blurred less (lens focal point distance)
float fApertureScale = 0.002;					// governs image blur scale (the bigger value, the stronger blur)
float fApertureCutoff = 0.25;					// manages the smoothness of the DoF (bigger value results in wider depth of field)

// Grain parameters
float fGrainFreq = 2450;						// movie grain frequency
float fGrainScale = 0.03;						// effect scale

// Anamorphic flare parameters (by default not used)
float fLuminance = 0.7;							// bright pass luminance value
float fModulate = 2.0;							// bright pass luminance multiplier (the bigger, the dimmer the effect is)
float fBlur = 4500.0;							// blur amount, manages the size of the flare

/**
 * Chromatic aberration function - given texture coordinate and a focus value
 * retrieves chromatically distorted color of the pixel. Each of the color
 * channels are displaced according to the pixel coordinate and its distance
 * from the center of the image. Also the DoF out-of-focus value is applied.
 * (http://en.wikipedia.org/wiki/Chromatic_aberration)
 */
float4 ChromaticAberration(float2 tex, float outOfFocus)
{
	float d = distance(tex, float2(0.1, 0.1));
	float f = smoothstep(fBaseRadius, fFalloffRadius, d) + outOfFocus * fFocusScale;
	float3 chroma = (f + fvChroma);
	
	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(SamplerColor, tr).r, tex2D(SamplerColor, tg).g, tex2D(SamplerColor, tb).b) * (1.1 - f);
	
	return float4(color * fChromaPower, 3.0);
}

/**
 * Pseudo-random number generator - returns a number generated according to the provided vector.
 */
float Random(float2 co)
{
    return frac(sin(dot(co.xy, float2(12.9898, 78.233))) * 43758.5453);
}

/**
 * Movie grain function - returns a random, time scaled value for the given pixel coordinate.
 */
float Grain(float3 tex)
{
	float r = Random(tex.xy);
	float grain = sin(PI * tex.z * r * fGrainFreq) * fGrainScale * r;
	return grain;
}

/**
 * Bright pass - rescales sampled pixel to emboss bright enough value.
 */
float3 BrightPass(float2 tex)
{
	float3 c = tex2D(SamplerColor, tex).rgb;
    float3 bC = max(c - fModulate * float3(fLuminance, fLuminance, fLuminance), 0.0f);
    float bright = dot(bC, 1.0f);
    bright = smoothstep(0.0f, 0.5f, bright);
    return lerp(0.0f, c, bright);
}

/**
 * Anamorphic sampling function - scales pixel coordinate
 * to stratch the image along one of the axels.
 * (http://en.wikipedia.org/wiki/Anamorphosis)
 */
float3 AnamorphicSample(int axis, float2 tex, float blur)
{
	tex = 1.5 * tex - 0.5;
	if (!axis) tex.x /= -blur;
	else tex.y /= -blur;
	tex = 0.5 * tex + 0.5;
	return BrightPass(tex);
}

///// Shaders ////////////////////////////////////////////////////////////////////////////////
// Vertex shader (Boris code)
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;
}

// Sharpen pixel shader (Matso code)
float4 PS_ProcessPass0(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
	float2 coord = IN.txcoord.xy;
	
	float4 Color = 9.0 * tex2D(SamplerColor, coord.xy);
	
	Color -= tex2D(SamplerColor, coord.xy + float2(-fvTexelSize.x, fvTexelSize.y) * fSharpScale);
	Color -= tex2D(SamplerColor, coord.xy + float2(0.0, fvTexelSize.y) * fSharpScale);
	Color -= tex2D(SamplerColor, coord.xy + float2(fvTexelSize.x, fvTexelSize.y) * fSharpScale);
	Color -= tex2D(SamplerColor, coord.xy + float2(fvTexelSize.x, 0.0) * fSharpScale);
	Color -= tex2D(SamplerColor, coord.xy + float2(fvTexelSize.x, -fvTexelSize.y) * fSharpScale);
	Color -= tex2D(SamplerColor, coord.xy + float2(0.0, -fvTexelSize.y) * fSharpScale);
	Color -= tex2D(SamplerColor, coord.xy + float2(-fvTexelSize.x, -fvTexelSize.y) * fSharpScale);
	Color -= tex2D(SamplerColor, coord.xy + float2(-fvTexelSize.x, 0.0) * fSharpScale);

	Color.a = 1.0;
	return Color;
}

// Depth of field pixel shader (Boris code, modified by Matso)
float4 PS_ProcessPass1(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
	float4 res;
	float2 coord = IN.txcoord.xy;

	float4 origcolor = tex2D(SamplerColor, coord.xy);

	float2 offset[16] =
	{
	 normalize(float2(1.0, 1.0) + float2(0.0, 1.0)),
	 normalize(float2(-1.0, -1.0) + float2(0.0, -1.0)),
	 normalize(float2(-1.0, 1.0) + float2(-1.0, 0.0)),
	 normalize(float2(1.0, -1.0) + float2(1.0, 0.0)),

	 normalize(float2(1.0, 0.0) + float2(1.0, 1.0)),
	 normalize(float2(-1.0, 0.0) + float2(-1.0, -1.0)),
	 normalize(float2(0.0, 1.0) + float2(-1.0, 1.0)),
	 normalize(float2(0.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),

	 float2(1.41, 1.41),
	 float2(-1.41, -1.41),
	 float2(-1.41, 1.41),
	 float2(1.41, -1.41)
	};

	float4 tcol = origcolor;
	float scenedepth = tex2D(SamplerDepth, IN.txcoord.xy).x;
	float scenefocus = tex2D(SamplerDepth, 0.5).x - fFocusBias;
#ifndef USE_SMOOTH_DOF
	float focus = fApertureScale * abs(scenedepth - scenefocus);
#else
	float focus = fApertureScale * smoothstep(0, fApertureCutoff, abs(scenedepth - scenefocus));
#endif
	
	for (int i = 1; i < 16; i++)
	{
		float2 tdir = offset[i].xy;
		coord.xy = IN.txcoord.xy + tdir.xy * focus;
#ifdef USE_CHROMA
		float4 ct = ChromaticAberration(coord.xy, focus);
#else
		float4 ct = tex2D(SamplerColor, coord.xy);
#endif
		tcol += ct;
	}
	
	tcol *= 0.04155555;
	res.xyz = tcol.xyz;

#ifdef USE_GRAIN	
	float3 grain = tex2D(SamplerNoise, coord.xy * 1920).rgb * Grain(float3(coord.xy, SEED));
	res.xyz += grain;
#endif
	
#ifdef USE_ANAMFLARE
	float3 anamFlare = AnamorphicSample(1.0, coord.xy, fBlur) * float3(0.03, 0.03, 0.03);
	res.xyz += anamFlare;
#endif

	res.w = 0.1;
	return res;
}

#ifdef ENABLE_SHARP
technique PostProcess
{
	pass P0
	{
		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 PS_ProcessPass0();

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

#ifdef ENABLE_DOF
technique PostProcess2
{
	pass P0
	{
		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 PS_ProcessPass1();

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