//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ENBSeries effect file
// visit http://enbdev.com for updates
// Copyright (c) 2007-2017 Boris Vorontsov
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//v1 is shadow
//v2 is lighting
#define MODE_V1



//+++++++++++++++++++++++++++++
//internal parameters, can be modified
//+++++++++++++++++++++++++++++
float	EShadowAmountV1
<
	string UIName="Lighting: ShadowAmountV1";
	string UIWidget="Spinner";
	float UIMin=0.0;
	float UIMax=1.0;
> = {0.5};

float	ELightingAmountV2
<
	string UIName="Lighting: LightingAmountV2";
	string UIWidget="Spinner";
	float UIMin=0.0;
	float UIMax=100.0;
> = {0.5};



//+++++++++++++++++++++++++++++
//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;
//changes in range 0..1, 0 means that night time, 1 - day time
float	ENightDayFactor;
//changes 0 or 1. 0 means that exterior, 1 - interior
float	EInteriorFactor;
//.x - current weather index, .y - incoming weather index, .z - weather transition, .w - time of the day in 24 standart hours. Weather index is value from _weatherlist.ini, for example WEATHER002 means index==2, but index==0 means that weather not captured.
float4	WeatherAndTime;
//adaptation delta time for focusing
float	FadeFactor;
//fov in degrees
float	FieldOfView;
//time in 0..24 format
float	GameTime;
//sun direction in world space
float4	SunDirection; //.w - 1 when sun is set
//constants set in enbhelper.dll, can be anything captured from game
float4	CustomShaderConstants1[8];

//transposed transform matrix view*projection and inverse of it
float4	MatrixVP[4];
float4	MatrixInverseVP[4];
float4	MatrixVPRotation[4];
float4	MatrixInverseVPRotation[4];
float4	MatrixView[4];
float4	MatrixInverseView[4];
float4	CameraPosition;


float4x4	MatrixWVP;
float4x4	MatrixWVPInverse;
float4x4	MatrixWorld;
float4x4	MatrixProj;
float4	FogParam; //x - nearclip, y - farclip, z - fog start, w - fog end
float4	FogFarColor;


//textures
texture2D texOriginal; //always first pass input texture
texture2D texColor; //result of each previous pass
texture2D texDepth;
texture2D texDepthMipMap;
texture2D texNormal;
texture2D texEnv;
texture2D texNoise;
texture2D texShadow;

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

sampler2D SamplerColor = sampler_state
{
	Texture   = <texColor>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;//NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	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 SamplerDepthMipMap = sampler_state
{
	Texture   = <texDepthMipMap>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

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

sampler2D SamplerEnv = sampler_state
{
	Texture   = <texEnv>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

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

sampler2D SamplerShadow = sampler_state
{
	Texture   = <texShadow>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;//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;
};



//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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;
}



float4 PS_Shadow(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
	float4	res;

	float4	color=tex2D(SamplerColor, IN.txcoord.xy);
	float4	shadowtex=tex2D(SamplerShadow, IN.txcoord.xy);
	float	depth=tex2D(SamplerDepth, IN.txcoord.xy).x;

	float4	origcolor=color;

	float4 tempvec;
	float4 worldpos;
	tempvec.xy=IN.txcoord.xy*2.0-1.0;
	tempvec.y=-tempvec.y;
	tempvec.z=depth;
	tempvec.w=1.0;
	worldpos.x=dot(tempvec, MatrixInverseVP[0]);
	worldpos.y=dot(tempvec, MatrixInverseVP[1]);
	worldpos.z=dot(tempvec, MatrixInverseVP[2]);
	worldpos.w=dot(tempvec, MatrixInverseVP[3]);
	worldpos.xyz/=worldpos.w;
	worldpos.w=1.0;
	worldpos.z=dot(worldpos, MatrixVP[2]);
	float	fogdist;
	fogdist=worldpos.z;
	float	fadefact=(FogParam.w - fogdist) / (FogParam.w - FogParam.z);
	fadefact=saturate(1.0-fadefact);
	//remove fog
	color.xyz=(color.xyz - FogFarColor.xyz*fadefact)/(1.00001-fadefact);
	color.xyz=max(color.xyz, 0.0);



	//remove from sides
	float4	normal=tex2D(SamplerNormal, IN.txcoord.xy);
	normal.xyz=normal.xyz*2.0-1.0;
	float4	normalpos;
	tempvec.xyz=normal.xyz;
	tempvec.x=-tempvec.x;
	tempvec.w=1.0;
	normalpos.x=dot(tempvec.xyz, MatrixInverseView[0]);
	normalpos.y=dot(tempvec.xyz, MatrixInverseView[1]);
	normalpos.z=dot(tempvec.xyz, MatrixInverseView[2]);
	normalpos.xyz=normalize(normalpos.xyz);
	float3	sunvec=SunDirection.xyz;
	float	sidefact=dot(normalpos.xyz, sunvec.xyz);
	sidefact*=saturate(SunDirection.z * 6.0); //if sun below horizon, disable this
	shadowtex*=saturate(1.0-sidefact * 6.0);
	shadowtex=lerp(shadowtex, 1.0, fadefact); //reduce based on fog, guess not required becaose of defog code
	shadowtex=lerp(1.0, shadowtex, EShadowAmountV1); //reduce in general

	//apply shadow
	color.xyz*=shadowtex;

	//apply fog again
	color.xyz=lerp(color.xyz, FogFarColor.xyz, fadefact);

	res=color;

	//ignore sky
	if (depth>=0.999999) res=origcolor;

	res.w=1.0; //color.w;
	return res;
}



//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
float4 PS_Lighting(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
	float4	res;

	float4	color=tex2D(SamplerColor, IN.txcoord.xy);
	float4	shadowtex=tex2D(SamplerShadow, IN.txcoord.xy);
	float	depth=tex2D(SamplerDepth, IN.txcoord.xy).x;

	float4	origcolor=color;

	float4 tempvec;
	float4 worldpos;
	tempvec.xy=IN.txcoord.xy*2.0-1.0;
	tempvec.y=-tempvec.y;
	tempvec.z=depth;
	tempvec.w=1.0;
	worldpos.x=dot(tempvec, MatrixInverseVP[0]);
	worldpos.y=dot(tempvec, MatrixInverseVP[1]);
	worldpos.z=dot(tempvec, MatrixInverseVP[2]);
	worldpos.w=dot(tempvec, MatrixInverseVP[3]);
	worldpos.xyz/=worldpos.w;
	worldpos.w=1.0;
	worldpos.z=dot(worldpos, MatrixVP[2]);
	float	fogdist;
	fogdist=worldpos.z;
	float	fadefact=(FogParam.w - fogdist) / (FogParam.w - FogParam.z);
	fadefact=saturate(1.0-fadefact);
	//remove fog
	color.xyz=(color.xyz - FogFarColor.xyz*fadefact)/(1.00001-fadefact);
	color.xyz=max(color.xyz, 0.0);



	//remove from sides
	float4	normal=tex2D(SamplerNormal, IN.txcoord.xy);
	normal.xyz=normal.xyz*2.0-1.0;
	float4	normalpos;
	tempvec.xyz=normal.xyz;
	tempvec.x=-tempvec.x;
	tempvec.w=1.0;
	normalpos.x=dot(tempvec.xyz, MatrixInverseView[0]);
	normalpos.y=dot(tempvec.xyz, MatrixInverseView[1]);
	normalpos.z=dot(tempvec.xyz, MatrixInverseView[2]);
	normalpos.xyz=normalize(normalpos.xyz);
	float3	sunvec=SunDirection.xyz;
	float	sidefact=dot(normalpos.xyz, sunvec.xyz);
	sidefact*=saturate(SunDirection.z * 2.0); //sun angle dependent and if below horizon, disable this
	shadowtex*=saturate(-sidefact);
	shadowtex=lerp(shadowtex, 0.0, fadefact); //reduce based on fog

	//kinda attempt to extract albedo
	float3	texonly=color;
	texonly=clamp(texonly, 0.001, 1.0);
	texonly.xyz=texonly.xyz/(0.5+dot(texonly.xyz, 0.3333));

	//apply lighting
	color.xyz+=texonly.xyz*shadowtex * ELightingAmountV2;

	//apply fog again
	color.xyz=lerp(color.xyz, FogFarColor.xyz, fadefact);

	res=color;


	//ignore sky
	if (depth>=0.999999) res=origcolor;

	res.w=1.0; //color.w;
	return res;
}



//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#ifdef MODE_V1
technique PostProcess
{
	pass P0
	{
		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 PS_Shadow();

		ALPHATESTENABLE=FALSE;
		SEPARATEALPHABLENDENABLE=FALSE;
		AlphaBlendEnable=FALSE;
		SRGBWRITEENABLE=FALSE;
	}
}
#endif //MODE_V1


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

		ALPHATESTENABLE=FALSE;
		SEPARATEALPHABLENDENABLE=FALSE;
		AlphaBlendEnable=FALSE;
		SRGBWRITEENABLE=FALSE;
	}
}
#endif //MODE_V2


