//Polik groNak's recreation of..
//LizTail's suggestion for pretty Bloom...
//as demonstrated in GIMP :)
//lol
//Also added HDR effect
//Also added Sparkle effect as demonstrated in Timeslip's HDR2

texture lastpass;
texture thisframe;
texture lastframe;

sampler s0 = sampler_state { magfilter=linear; AddressU=Clamp; AddressV=Clamp;};
sampler s1 = sampler_state { texture = <lastpass>; magfilter=linear; AddressU=Clamp; AddressV=Clamp; };
sampler s2 = sampler_state { texture=<thisframe>; magfilter=linear; AddressU=Clamp; AddressV=Clamp;};


// **MGE VARIABLES**
float2 rcpres;
float4 HDR;
//Preview uses HDR=0, thus everything will show up bright
//float4 HDR = float4(0.0,0,0,0);
//float4 HDR = float4(0.1,0.1,0.1,0.1);
//float4 HDR = float4(0.2,0.2,0.2,0.2);
//float4 HDR = float4(0.3,0.3,0.3,0.3);
//float4 HDR = float4(0.7,0.7,0.7,0.7);
//float4 HDR = float4(0.5,0.5,0.5,0.5);
//float4 HDR = float4(1,1,1,1);


// **BLOOM VARIABLES** 

const static float scale = 6.5f;
//Scale of bloom stretch across the screen
//decrease for smaller bloom that is more accurate
//increase for larger bloom that is less accurate

const static float BloomBoost = 1.0f;
//boost in bloom brightness, increase for brighter bloom

static const float SparkleScale = 5.2f;
//boost in sparkle brightness, increase for brighter sparkles

// **HDR VARIABLES** 

static const float3 midlevel = sqrt(HDR+float3(0.05,0.05,0.05))-float3(0.1,0.1,0.1);
static const float3 midlevel2 = float3(0.5,0.5,0.5);
static const float3 midlevel3 = (float3(0.3,0.3,0.3) + HDR*0.8);
//These are a pain to tweak just right, don't mess with them unless you really want to play around


// **OTHER VARIABLES** 
const static int kernelsize = 7;
const static int kernelsize2 = 4;
const static int S2g_cKernelSize = 7;
float2 S2PixelKernelH[S2g_cKernelSize] =
{
//    { -4, 0 },
    { -3, 0 },
    { -2, 0 },
    { -1, 0 },
    {  0, 0 },
    {  1, 0 },
    {  2, 0 },
    {  3, 0 },
//    {  4, 0 },
};

float2 S2PixelKernelV[S2g_cKernelSize] =
{
//    { 0, -4 },
    { 0, -3 },
    { 0, -2 },
    { 0, -1 },
    { 0,  0 },
    { 0,  1 },
    { 0,  2 },
    { 0,  3 },
//    { 0,  4 },
};

static const float S2BlurWeights[S2g_cKernelSize] = 
{
//    0.058764,
    0.164759,
    0.170985,
    0.176033,
    0.179471,
    0.176033,
    0.170985,
    0.164759,
//    0.058764,
};
const float2 blurPixs2[kernelsize2] = 
{
	{  1.5,  0.5},
	{  0.5, -1.5},
	{ -0.5,  1.5},
	{ -1.5, -0.5},
};
const float1 blurPixs[kernelsize] = 
{
//	{-4.0},
	{-3.0},
	{-2.00},
	{-1.000},
	{ 0.0},
	{ 1.000},
	{ 2.00},
	{ 3.0},
//	{ 4.0}
};
const float1 blurMags[kernelsize] = 
{
//	{0.13},
//	{0.16},
//	{0.18},
//	{0.192},
	{0.05},
	{0.14},
	{0.23},
	{0.32},
	{0.23},
	{0.14},
	{0.05},
//	{0.192},
//	{0.18},
//	{0.16},
//	{0.13}
};



float4 MyBloomH( float2 Tex : TEXCOORD0 ) : COLOR0
{
	float3 ColorBloom = 0;
	float3 ColorNew = 0;

	if (Tex.x*(scale) > 1.05 || Tex.y*(scale) > 1.05){
	}else{

	for (int i=0; i<kernelsize; i++){
		ColorBloom = tex2D( s1, Tex + float2(blurPixs[i],0)*rcpres );
		ColorBloom *= float3(blurMags[i],blurMags[i],blurMags[i]);
		ColorNew += ColorBloom;
	}

	}
	return float4(saturate(ColorNew*BloomBoost), 1);
}
float4 MyBloomV( float2 Tex : TEXCOORD0 ) : COLOR0
{
	float3 ColorBloom = 0;
	float3 ColorNew = 0;

	if (Tex.x*(scale) > 1.05 || Tex.y*(scale) > 1.05){
	}else{

	for (int i=0; i<kernelsize; i++){
		ColorBloom = tex2D( s1, Tex + float2(0,blurPixs[i])*rcpres );
		ColorBloom *= float3(blurMags[i],blurMags[i],blurMags[i]);
		ColorNew += ColorBloom;
	}

	}
	return float4(saturate(ColorNew*BloomBoost), 1);
}

float4 BloomSparkleV( in float2 Tex : TEXCOORD0 ) : COLOR0
{
    float3 Color = tex2D( s1, Tex );

    float3 Color2=0;
	float3 Color3=0;
    for (int i = 0; i < S2g_cKernelSize; i++)
    {    
        Color3 = tex2D( s2, Tex + (S2PixelKernelV[i]*rcpres) );
	//Color2 += Color3 * Color3 * Color3 * Color3 * S2BlurWeights[i];
	Color2 += saturate(Color3-midlevel3)*S2BlurWeights[i];
    }

    Color2 = saturate(Color2);
	Color3 = tex2D( s2, Tex );
	//Color2 *= saturate((Color2/Color3)-float3(1,1,1));
	Color2 *= SparkleScale;
	Color2 = saturate(Color2-Color);

	//float mult = saturate((Color2.r+Color2.g+Color2.b)/(Color3.r+Color3.g+Color3.b));
	//Color2 = float3(mult,mult,mult) - float3(1,1,1);
	//float SparkDiff = saturate(mult);
	//return float4(saturate((Color2*float3(SparkDiff,SparkDiff,SparkDiff))+Color), 1.0f);
	return float4(Color2+Color,1.0f);
}

float4 BloomSparkleH( in float2 Tex : TEXCOORD0 ) : COLOR0
{
    float3 Color = tex2D( s1, Tex );


    float3 Color2=0;
	float3 Color3=0;
    for (int i = 0; i < S2g_cKernelSize; i++)
    {    

        Color3 = tex2D( s2, Tex + (S2PixelKernelH[i]*rcpres) );
	//Color2 += Color3 * Color3 * Color3 * Color3 * S2BlurWeights[i];
	Color2 += saturate(Color3-midlevel3)*S2BlurWeights[i];
    }

    Color2 = saturate(Color2);
	Color3 = tex2D( s2, Tex );
	//Color2 *= saturate((Color2/Color3)-float3(1,1,1));
	Color2 *= SparkleScale;
	Color2 = saturate(Color2-Color);

	//float mult = (Color2.r+Color2.g+Color2.b)/3-(Color.r+Color.g+Color.b)/3;
	//float SparkDiff = saturate(mult);
	//return float4(saturate((Color2*float3(SparkDiff,SparkDiff,SparkDiff))+Color), 1.0f);
	return float4(Color2+Color,1.0f);
}



float4 ThreshDownScale( float2 Tex : TEXCOORD0 ) : COLOR0
{
	float3 ColorNew = 0;
	if (Tex.x*(scale) > 1.05 || Tex.y*(scale) > 1.05){
	}else{
	ColorNew = saturate(tex2D( s0, Tex*(scale) )-midlevel);
	for (int i=0; i<4; i++){
		ColorNew += saturate(tex2D( s0, Tex*(scale) + blurPixs2[i]*rcpres )-midlevel);
	}
	}
	return float4(ColorNew/5, 1);
}


float4 UpScaleCombine( float2 Tex : TEXCOORD0 ) : COLOR0
{
	float3 ColorNew = tex2D( s1, Tex/(scale) );
	float3 ColorOrig = tex2D( s2, Tex );
	ColorNew = (saturate(ColorOrig+midlevel2)-midlevel2)*(0.75/(HDR+float3(0.49,0.49,0.49))) + saturate(ColorOrig-midlevel2)*saturate(ColorOrig-midlevel2)*4*1.0+ColorNew*(0.75/(HDR+float3(0.49,0.49,0.49)));

	return float4(ColorNew, 1.0f);

}



technique T0
{

    pass p2{PixelShader = compile ps_2_0 ThreshDownScale();}

    pass p3{PixelShader = compile ps_2_0 MyBloomH();}
    pass p4{PixelShader = compile ps_2_0 MyBloomV();}

    pass p7{PixelShader = compile ps_2_0 UpScaleCombine();}

    pass p9{PixelShader = compile ps_2_0 BloomSparkleV();}
    pass p9{PixelShader = compile ps_2_0 BloomSparkleH();}

}
