// DP3 for LowPCs edited by sunjianyu12345

float4 BloomParameters;
float4 TempParameters;
float4 ScreenSize;
float BloomRadius3 = 64;
float BloomRadius4 = 128;
float MixFactor = 0.05;


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



//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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;//1.0/(bloomtexsize*2.0)

return OUT;
}


//zero pass HQ, input texture is fullscreen
//SamplerBloom1 - fullscreen texture
//zero pass HQ, input texture is fullscreen
//SamplerBloom1 - fullscreen texture
float4 PS_BloomPrePass(VS_OUTPUT_POST In) : COLOR
{
float4 bloomuv;
float4 overbright;
float bthreshold = 15;



float4 bloom=tex2D(SamplerBloom1, In.txcoord0);
const float2 offset[16]=
{
float2(-0.94201624, -0.39906216),
float2( 0.94558609, -0.76890725),
float2(-0.09418410, -0.92938870),
float2( 0.34495938,  0.29387760),
float2(-0.91588581,  0.45771432),
float2(-0.81544232, -0.87912464),
float2(-0.38277543,  0.27676845),
float2( 0.97484398,  0.75648379),
float2( 0.44323325, -0.97511554),
float2( 0.53742981, -0.47373420),
float2(-0.26496911, -0.41893023),
float2( 0.79197514,  0.19090188),
float2(-0.24188840,  0.99706507),
float2(-0.81409955,  0.91437590),
float2( 0.19984126,  0.78641367),
float2( 0.14383161, -0.14100790)
};

float2 screenfact=1.0;
screenfact.y*=ScreenSize.z;
screenfact.xy*=TempParameters.z*1.5;
float4 srcbloom=bloom;

for (int i=0; i<16; i++)
{
 bloomuv.xy= In.txcoord0.xy;

 //bloomuv.xy=offset[i];
 //bloomuv.xy=(bloomuv.xy*screenfact.xy)+In.txcoord0.xy;//-(1.0/256.0);//-(1.0/512.0);
 
 bloomuv.x = bloomuv.x - 0.5;
 bloomuv.y = 0.5 - bloomuv.y;

 bloomuv.xy -= bloomuv.xy* floor(i*0.25) *0.25;
 bloomuv.xy = -bloomuv.xy;

 bloomuv.xy *= 4 + i * 0.3;

 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.053;//0.125;

bloom.w=1.0;
return bloom;
}



//first and second passes draw to every texture
//twice, after computations of these two passes,
//result is set as input to next cycle

//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[16]=
{
float2(-0.94201624, -0.39906216),
float2( 0.94558609, -0.76890725),
float2(-0.09418410, -0.92938870),
float2( 0.34495938,  0.29387760),
float2(-0.91588581,  0.45771432),
float2(-0.81544232, -0.87912464),
float2(-0.38277543,  0.27676845),
float2( 0.97484398,  0.75648379),
float2( 0.44323325, -0.97511554),
float2( 0.53742981, -0.47373420),
float2(-0.26496911, -0.41893023),
float2( 0.79197514,  0.19090188),
float2(-0.24188840,  0.99706507),
float2(-0.81409955,  0.91437590),
float2( 0.19984126,  0.78641367),
float2( 0.14383161, -0.14100790)
};
float2 screenfact=1.0;
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<16; i++)
{
 bloomuv.xy=offset[i]*BloomParameters.x;
 bloomuv.xy=(bloomuv.xy*screenfact.xy)+In.txcoord0.xy;//-(1.0/256.0);//-(1.0/512.0);

 bloomuv2.xy=offset[i]*BloomRadius3;
 bloomuv2.xy=(bloomuv2.xy*screenfact.xy)+In.txcoord0.xy;

 //v2
 float4 tempbloom1=tex2D(SamplerBloom1, bloomuv.xy);
 float4 tempbloom2=tex2D(SamplerBloom1, bloomuv2.xy);

 float4 tempbloom = lerp(tempbloom1, tempbloom2, MixFactor);
 bloomadd+=tempbloom;
 
 bloom.xyz = max(bloom.xyz, tempbloom.xyz*0.99);




}
//v1
bloomadd*=0.111111;
//v0
bloom.xyz=lerp(bloomadd.xyz, bloom.xyz, BloomParameters.w);


//float3 violet=float3(0.78, 0.5, 1.0);
//float3 violet=float3(0.6, 0.4, 1.0);//v2
float3 violet=float3(0.6, 0.5, 1.0);//v3

//this applies when white
//float gray=0.104*dot(srcbloom.xyz, 0.333);//max(srcbloom.x, max(srcbloom.y, srcbloom.z));
//this applies on dark and when contrast
float ttt=dot(bloom.xyz, 0.333)-dot(srcbloom.xyz, 0.333);
ttt=max(ttt, 0.0);
float gray=BloomParameters.z*ttt;//max(srcbloom.x, max(srcbloom.y, srcbloom.z));
float mixfact=(gray/(1.0+gray));
mixfact*=1.0-saturate((TempParameters.w-1.0)*0.3);
violet.xy+=saturate((TempParameters.w-1.0)*0.3);
violet.xy=saturate(violet.xy);
bloom.xyz*=lerp(1.0, violet.xyz, mixfact);

bloom.w=1.0;
return bloom;
}


//second pass
//SamplerBloom1 is result of first pass
float4 PS_BloomTexture2(VS_OUTPUT_POST In) : COLOR
{
float4 bloomuv;
float4 bloomuv2;

float4 bloom=tex2D(SamplerBloom1, In.txcoord0);
const float2 offset[16]=
{
float2(-0.94201624, -0.39906216),
float2( 0.94558609, -0.76890725),
float2(-0.09418410, -0.92938870),
float2( 0.34495938,  0.29387760),
float2(-0.91588581,  0.45771432),
float2(-0.81544232, -0.87912464),
float2(-0.38277543,  0.27676845),
float2( 0.97484398,  0.75648379),
float2( 0.44323325, -0.97511554),
float2( 0.53742981, -0.47373420),
float2(-0.26496911, -0.41893023),
float2( 0.79197514,  0.19090188),
float2(-0.24188840,  0.99706507),
float2(-0.81409955,  0.91437590),
float2( 0.19984126,  0.78641367),
float2( 0.14383161, -0.14100790)
};
float2 screenfact=1.0;
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=0.0;
sincos(0.19635, rotvec.x, rotvec.y);
for (int i=0; i<16; 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;//-(1.0/256.0);//-(1.0/512.0);

 float4 tempbloom1 = tex2D(SamplerBloom1, bloomuv.xy);



 bloomuv2.xy=offset[i];
 bloomuv2.xy=reflect(bloomuv2.xy, rotvec.xy);
 bloomuv2.xy*=BloomRadius4;
 bloomuv2.xy=(bloomuv2.xy*screenfact.xy)+In.txcoord0.xy;//-(1.0/256.0);//-(1.0/512.0);
 float4 tempbloom2 = tex2D(SamplerBloom1, bloomuv2.xy);

 float4 tempbloom = lerp(tempbloom1, tempbloom2, MixFactor);

 bloom+=tempbloom;

}
bloom*=0.05;//0.125;

bloom.w=1.0;
return bloom;
}



//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*=0.2;
temp = bloom;

//v2
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.3);

//bloom =tex2D(SamplerBloom1, In.txcoord0);

bloom.w=1.0;
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;
}
}