//+++++++++++++++++++++++++++++++++++++++++++++++++++
// ENBSeries Bloom file
// visit http://enbdev.com for updates
// Copyright 2007-2013 (c) Boris Vorontsov
// SuperAria18's Chromatic Light-shafts enbbloom file
// SuperAria18, John Chapman, MartyMcfly, GP65
//+++++++++++++++++++++++++++++++++++++++++++++++++++

// Bloom Settings

float BloomSquishy=0.25;//Controls how large the bloom is. Higher, more bloom
float3 ChromaticDistortion=float3(-0.02, 0.02, 0.02);//RGB color dispersal on the light shafts. Higher, more dispersed

//++++++++++++++++++++++++++++++++++++++++++++

float4	BloomParameters;
float4	TempParameters;
float4	ScreenSize;

struct VS_OUTPUT_POST
{
	float4 vpos  : POSITION;
	float2 txcoord0 : TEXCOORD0;
};
struct VS_INPUT_POST
{
	float3 pos  : POSITION;
	float2 txcoord0 : TEXCOORD0;
};

texture2D texBloom1;
texture2D texBloom2;
texture2D texBloom3;
texture2D texBloom4;
texture2D texBloom5;

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

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

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

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

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

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

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

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

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

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

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

	OUT.txcoord0.xy=IN.txcoord0.xy+TempParameters.xy;

	return OUT;
}
float4 texDistorted(sampler2D tex, float2 uv, float2 offset, float3 distortion, float threshold)
{
	float4 color=0;
	float3 temp;
	float2 tempuv=uv.xy + offset.xy * distortion.x;
	if(tempuv.x >= 0.0 && tempuv.x <=1.0 && tempuv.y >= 0.0 && tempuv.y <=1.0)
	{
		temp.xyz=tex2D(tex, tempuv).xyz;
		temp.xyz=(dot(temp.xyz, 0.3333) > threshold) ? temp.xyz : 0.0;
		color.x+=temp.x;
	}
	
	tempuv=uv.xy + offset.xy * distortion.y;
	if(tempuv.x >= 0.0 && tempuv.x <=1.0 && tempuv.y >= 0.0 && tempuv.y <=1.0)
	{
		temp.xyz=tex2D(tex, tempuv).xyz;
		temp.xyz=(dot(temp.xyz, 0.3333) > threshold) ? temp.xyz : 0.0;
		color.y+=temp.y;
	}
	
	tempuv=uv.xy + offset.xy * distortion.z;
	if(tempuv.x >= 0.0 && tempuv.x <=1.0 && tempuv.y >= 0.0 && tempuv.y <=1.0)
	{
		temp.xyz=tex2D(tex, tempuv).xyz;
		temp.xyz=(dot(temp.xyz, 0.3333) > threshold) ? temp.xyz : 0.0;
		color.z+=temp.z;
	}
	
	color.w=(dot(color.xyz, 0.3333) > 0) ? 1.0 : 0.0;

	return color;
}
//zero pass
float4 PS_BloomPrePass(VS_OUTPUT_POST In) : COLOR
{
	float4 bloomuv;
	float4	overbright;
	float	bthreshold = 20;
	
	float4 bloom=tex2D(SamplerBloom1, In.txcoord0);
	/*const 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)
	};*/
//The stretching begins
const float2 offset[16]=
{
float2(-0.94201624, -100.39906216),
float2( 0.94558609, -100.76890725),
float2(-0.09418410, -100.92938870),
float2( 0.34495938, -100.29387760),
float2(-0.91588581, -100.45771432),
float2(-0.81544232, -100.87912464),
float2(-0.38277543, -100.27676845),
float2( 0.97484398, -100.75648379),
float2( 0.44323325, -100.97511554),
float2( 0.53742981, -100.47373420),
float2(-0.26496911, -100.41893023),
float2( 0.79197514, -100.19090188),
float2(-0.24188840, -100.99706507),
float2(-0.81409955, -100.91437590),
float2( 0.19984126, -100.78641367),
float2( 0.14383161, -100.14100790)
};
	float2 screenfact=1.0;
	screenfact.y*=ScreenSize.z;
	screenfact.xy*=TempParameters.z*10;
	float4 srcbloom=bloom;
	for (int i=0; i<8; i++)
	{
		bloomuv.xy= In.txcoord0.xy;
		bloomuv.x = bloomuv.x - 0.5;
		bloomuv.y = 0.5 - bloomuv.y;
		bloomuv.xy -= bloomuv.xy* floor(i*0.25) *2;
		bloomuv.xy = -bloomuv.xy;
		bloomuv.xy *= 0.2 + i * 0.1;
		bloomuv.x = bloomuv.x + 0.5;
		bloomuv.y = 0.5 - bloomuv.y;		
		bloomuv.xy = saturate(bloomuv.xy);
		overbright = tex2D(SamplerBloom1, bloomuv.xy);
		overbright.w = dot(overbright.xyz, 0.3333);
		overbright.w = saturate(overbright.w - bthreshold);
		if(overbright.w)bloom.xyz += overbright.xyz;
		else
		{
		bloomuv.xy=offset[i];
		bloomuv.xy=(bloomuv.xy*screenfact.xy)+In.txcoord0.xy;//-(1.0/256.0);//-(1.0/512.0);
		bloom+=tex2D(SamplerBloom1, bloomuv.xy);
		}
	}
	bloom*=0.07;//0.125;

float4	flare=0.0;
float3	chromadistortion=ChromaticDistortion;
float2	centeruv=1.0;
float2	flareuv=(centeruv.xy - In.txcoord0.xy) * -2.0;//Dispersal
float2	halouv=normalize(flareuv) * -2.0;
float4 temp=tex2D(SamplerBloom1, centeruv.xy);
for(int i=1; i < 8; i++)
{
float2	offset=flareuv * float(i);
flare+=texDistorted(SamplerBloom1, In.txcoord0.xy + offset.xy, 
offset.xy, chromadistortion.xyz, 60.0)*0.0;
}
flare+=texDistorted(SamplerBloom1, In.txcoord0.xy + halouv.xy, 
halouv.xy, chromadistortion.xyz, 60.0)*0.0;
	
	bloom.w=0.2;
	bloom+=flare;
	
	return bloom;
}


//first pass
//SamplerBloom1 is result of prepass or second pass from cycle
float4 PS_BloomTexture1(VS_OUTPUT_POST In) : COLOR
{
	float4 bloomuv;
	float4 bloomuv2;
	float4 bloom=tex2D(SamplerBloom1, In.txcoord0);
	const 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)
	};
	float2 screenfact=0.2;
	screenfact.y*=ScreenSize.z;
	screenfact.xy/=ScreenSize.x;
	float4 srcbloom=bloom;
	float step=(TempParameters.w-0.5)*1.5;
	screenfact.xy*=step;

	float4 bloomadd=bloom;
	for (int i=0; i<8; i++)
	{
		bloomuv.xy=offset[i]*BloomParameters.x;
		bloomuv.xy=(bloomuv.xy*screenfact.xy)+In.txcoord0.xy;
		float4 tempbloom=tex2D(SamplerBloom1, bloomuv.xy);
		bloomadd+=tempbloom;
		bloom.xyz=max(bloom.xyz, tempbloom.xyz*1.5);
	}
	bloomadd*=0.1;
	bloom.xyz=lerp(bloomadd.xyz, bloom.xyz, BloomParameters.w);

	float3 violet=float3(1.2, 1.0, 1.0);
	float ttt=dot(bloom.xyz, 0.333)-dot(srcbloom.xyz, 0.333);
	ttt=max(ttt, 0.0);
	float gray=BloomParameters.z*ttt;
	float mixfact=(gray/(1.0+gray));
	mixfact*=1.0*saturate((TempParameters.w-1.0)*0.7);
	violet.xy+=saturate((TempParameters.w-1.0)*255.0);
	violet.xy=saturate(violet.xy);
	bloom.xyz*=lerp(1.0, violet.xyz, mixfact);

	bloom.w=0.1;
	
	return bloom;
}

//second pass
float4 PS_BloomTexture2(VS_OUTPUT_POST In) : COLOR
{
	float4 bloomuv;

	float4 bloom=tex2D(SamplerBloom2, In.txcoord0);
	const float2 offset[8]=
	{
		float2(0.707, -50.707),
		float2(0.707, -50.707),
		float2(-0.707, -50.707),
		float2(-0.707, -50.707),
		float2(0.0, -50.0),
		float2(0.0, -50.0),
		float2(1.0, -50.0),
		float2(-1.0, -50.0)
};
	float2 screenfact=0.2;
	screenfact.y*=ScreenSize.z;
	screenfact.xy/=ScreenSize.x;
	float4 srcbloom=bloom;

	float step=(TempParameters.w-0.5)*1.2;//v3
	screenfact.xy*=step;
	float4 rotvec=2;
	sincos(0.19635, rotvec.x, rotvec.y);
	for (int i=0; i<8; i++)
	{
		bloomuv.xy=offset[i];
		bloomuv.xy=reflect(bloomuv.xy, rotvec.xy);
		bloomuv.xy*=BloomParameters.y;
		//separate code is much faster without constant table operations
		bloomuv.xy=(bloomuv.xy*screenfact.xy)+In.txcoord0.xy;
		bloom+=tex2D(SamplerBloom1, bloomuv.xy);
	}
	bloom*=0.1;
	bloom.w=0.2;
	
	return bloom;

}

float3 BrightPass(float2 tex)
{
	float3 c = tex2D(SamplerBloom5, tex).rgb;
	float3 bC = max(c - float3(0.2, 0.2, 0.2), 0.0);//Brightness Pass
	float bright = dot(bC, 20);
	bright = smoothstep(0.0f, 0.5f, bright);
	return lerp(0.0, c, bright);
}
float3 AnamorphicSample(int axis, float2 tex, float blur)
{
	float2 oritex=tex;
	tex = 2.0 * tex - 1.0;
	if (!axis) tex.x /= -blur;
	else tex.y /= -blur;
	tex = 0.5 * tex + 0.5;
	return BrightPass(tex);
}

float4 PS_ProcessPass_Anamorphic(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
	float4 res;
	float2 coord = IN.txcoord0.xy;
	float3 anamFlare = AnamorphicSample(0, coord.xy, 10) * float3(0.2, 0.1, 0.7);//Size and RGB color
	res.rgb = anamFlare * 0.175;//Intensity
	res.a = 1.0;
	return res;
}
//last pass, mix several bloom textures
//SamplerBloom5 is the result of prepass
float4 PS_BloomPostPass(VS_OUTPUT_POST In) : COLOR
{
	float4 bloom;
	float4 temp;
	//v1
	bloom =tex2D(SamplerBloom1, In.txcoord0);
	bloom+=tex2D(SamplerBloom2, In.txcoord0);
	bloom+=tex2D(SamplerBloom3, In.txcoord0);
	bloom+=tex2D(SamplerBloom4, In.txcoord0);
	bloom+=tex2D(SamplerBloom5, In.txcoord0);
	bloom*=BloomSquishy;
	temp = bloom;
	

	//v2 CAN BE DISABLED IF NEEDED
	float4 bloom1=tex2D(SamplerBloom1, In.txcoord0);
	float4 bloom2=tex2D(SamplerBloom2, In.txcoord0);
	float4 bloom3=tex2D(SamplerBloom3, In.txcoord0);
	float4 bloom4=tex2D(SamplerBloom4, In.txcoord0);
	float4 bloom5=tex2D(SamplerBloom5, In.txcoord0);
	bloom=max(bloom1, bloom2);
	bloom=max(bloom, bloom3);
	bloom=max(bloom, bloom4);
	bloom=max(bloom, bloom5);

	bloom = lerp(temp, bloom, 0.35);

	bloom.w=0.5;
	
	return bloom;
}
technique BloomPrePass
{
    pass p0
    {
	VertexShader = compile vs_3_0 VS_Bloom();
	PixelShader  = compile ps_3_0 PS_BloomPrePass();

	COLORWRITEENABLE=ALPHA|RED|GREEN|BLUE;
	CullMode=NONE;
	AlphaBlendEnable=FALSE;
	AlphaTestEnable=FALSE;
	SEPARATEALPHABLENDENABLE=FALSE;
	FogEnable=FALSE;
	SRGBWRITEENABLE=FALSE;
	}

 }
technique BloomTexture1
{
    pass p0
    {
	VertexShader = compile vs_3_0 VS_Bloom();
	PixelShader  = compile ps_3_0 PS_BloomTexture1();

	COLORWRITEENABLE=ALPHA|RED|GREEN|BLUE;
	CullMode=NONE;
	AlphaBlendEnable=FALSE;
	AlphaTestEnable=FALSE;
	SEPARATEALPHABLENDENABLE=FALSE;
	FogEnable=FALSE;
	SRGBWRITEENABLE=FALSE;
	}
	
}

technique BloomTexture2
{
    pass p0
    {
	VertexShader = compile vs_3_0 VS_Bloom();
	PixelShader  = compile ps_3_0 PS_BloomTexture2();

	COLORWRITEENABLE=ALPHA|RED|GREEN|BLUE;
	CullMode=NONE;
	AlphaBlendEnable=FALSE;
	AlphaTestEnable=FALSE;
	SEPARATEALPHABLENDENABLE=FALSE;
	FogEnable=FALSE;
	SRGBWRITEENABLE=FALSE;
	}
}
technique BloomPostPass
{
	 pass p0
	{
		VertexShader = compile vs_3_0 VS_Bloom();
		PixelShader  = compile ps_3_0 PS_BloomPostPass();
		
	COLORWRITEENABLE=ALPHA|RED|GREEN|BLUE;
	CullMode=NONE;
	AlphaBlendEnable=FALSE;
	AlphaTestEnable=FALSE;
	SEPARATEALPHABLENDENABLE=FALSE;
	FogEnable=FALSE;
	SRGBWRITEENABLE=FALSE;

	}

	pass p1
	{
			AlphaBlendEnable = true;
			SrcBlend = One;
			DestBlend = One;

		VertexShader = compile vs_3_0 VS_Bloom();
		PixelShader  = compile ps_3_0 PS_ProcessPass_Anamorphic();

	}
}
