float4 TESR_Flare_fFlareThreshold;
float4 TESR_Flare_fHaloThreshold;
float4 TESR_Flare_fFlareGain;
float4 TESR_Flare_fHaloGain;
float4 TESR_ReciprocalResolution;

#define rcpres TESR_ReciprocalResolution

sampler2D TESR_SourceBuffer : register(s0) = sampler_state { AddressU = CLAMP; AddressV = CLAMP; MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = NONE; };
sampler2D TESR_RenderedBuffer : register(s1) = sampler_state { AddressU = CLAMP; AddressV = CLAMP; MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = NONE; };

static const float2 OffsetMaskH = float2(1.0f, 0.0f);
static const float2 OffsetMaskV = float2(0.0f, 1.0f);
static const float2 BlurOffsets[13] = 
{
	float2(-6.0f * rcpres[0], -6.0f * rcpres[1]),
	float2(-5.0f * rcpres[0], -5.0f * rcpres[1]),
	float2(-4.0f * rcpres[0], -4.0f * rcpres[1]),
	float2(-3.0f * rcpres[0], -3.0f * rcpres[1]),
	float2(-2.0f * rcpres[0], -2.0f * rcpres[1]),
	float2(-1.0f * rcpres[0], -1.0f * rcpres[1]),
	float2( 0.0f * rcpres[0],  0.0f * rcpres[1]),
	float2( 1.0f * rcpres[0],  1.0f * rcpres[1]),
	float2( 2.0f * rcpres[0],  2.0f * rcpres[1]),
	float2( 3.0f * rcpres[0],  3.0f * rcpres[1]),
	float2( 4.0f * rcpres[0],  4.0f * rcpres[1]),
	float2( 5.0f * rcpres[0],  5.0f * rcpres[1]),
	float2( 6.0f * rcpres[0],  6.0f * rcpres[1])
};

static const float BlurWeights[13] = 
{
    0.002216,
    0.008764,
    0.026995,
    0.064759,
    0.120985,
    0.176033,
    0.199471,
    0.176033,
    0.120985,
    0.064759,
    0.026995,
    0.008764,
    0.002216,
};
struct VS_OUTPUT
{
   	float4 Position   : POSITION;
    float2 TexCoord  : TEXCOORD0;
};

struct VS_INPUT
{
   	float4 Position   : POSITION0;
    float2 TexCoord  : TEXCOORD0;
};

//------------------------------------
VS_OUTPUT VS_Comb(VS_INPUT IN) 
{
    VS_OUTPUT OUT;
    OUT.Position = IN.Position;
    OUT.TexCoord=IN.TexCoord;
    return OUT;
}

float4 BlurPass(VS_OUTPUT IN, uniform float2 OffsetMask) : COLOR0
{
	float4 Color = 0;
if (((IN.TexCoord.x>=0.5) && (IN.TexCoord.y>=0.5))||((IN.TexCoord.x<=0.25)&&(IN.TexCoord.x>=0.125))){
    for (int i = 0; i < 13; i++)
    {
		Color += tex2D(TESR_RenderedBuffer, IN.TexCoord + BlurOffsets[i] * OffsetMask) * BlurWeights[i];
    }
};
    return Color;
}

float4 PS_Halo(VS_OUTPUT IN, uniform sampler2D tex) : COLOR0
{
 float4 c;
 float lum;
 float2 HaloDir;
 float lum_mod;
 float lum_mul;
 if ((IN.TexCoord.x>=0.5) && (IN.TexCoord.y>=0.5)){
 HaloDir=IN.TexCoord-0.75;
 lum_mod=length(HaloDir)*2;
 lum_mul=(lum_mod-.2);
 HaloDir=normalize(HaloDir)*lum_mul;
 lum_mod= abs(lum_mul)/(lum_mod+0.2);
 HaloDir=0.5-HaloDir;
 c=tex2D(tex,HaloDir);
 lum=max(length(c.xyz),TESR_Flare_fHaloThreshold.x);
 lum=lum-TESR_Flare_fHaloThreshold.x;
 lum*=lum_mod;
 lum*=TESR_Flare_fHaloGain.x;
 lum*=lum;
 c=pow(c,10)*lum;
 }else if ((IN.TexCoord.x<=0.25)&&(IN.TexCoord.x>=0.125)) {
 HaloDir=float2(IN.TexCoord.x*8-1.0f,IN.TexCoord.y);
 c=tex2D(tex,HaloDir);
 lum=max(length(c.xyz),TESR_Flare_fFlareThreshold.x);
 lum=lum-TESR_Flare_fFlareThreshold.x;
 lum*=TESR_Flare_fFlareGain.x;
 lum*=lum;
 c=pow(c,10)*lum;
 }else{c=0;};
return c;
}

float4 PS_Reflect(VS_OUTPUT IN, uniform sampler2D tex, uniform float ScaleFactor, uniform float RefIntensity) : COLOR0
{
float4 c;
float2 RefCoord;
if ((IN.TexCoord.x>=0.5) && (IN.TexCoord.y>=0.5)){
float2 RefCoord=IN.TexCoord-0.75;
RefCoord=RefCoord*ScaleFactor+0.75;
c=tex2D(tex,RefCoord)*RefIntensity;
c+=tex2D(tex,IN.TexCoord);
}else{c=tex2D(tex,IN.TexCoord);};
return c;
}

float4 PS_Comb(VS_OUTPUT IN, uniform sampler2D tex, uniform sampler2D tex2) : COLOR
{
float4 c=tex2D(tex2,IN.TexCoord);
float2 HaloSeek=IN.TexCoord/2+0.5;
float2 AnamorphSeek=float2(IN.TexCoord.x/8+0.125,IN.TexCoord.y);
c+=tex2D(tex,HaloSeek);
c+=tex2D(tex,AnamorphSeek);
c+=tex2D(tex,float2(0.28125,.75)-AnamorphSeek/2)/4;
return c;
};

float4 PS_HeavyBlur(VS_OUTPUT IN, uniform sampler2D tex, uniform float AnamorphicRange, uniform float RadialRange) : COLOR0
{
 float4 c=0;
 float AngularOffset;
 int BlurStep;
 if ((IN.TexCoord.x>=0.5) && (IN.TexCoord.y>=0.5)){
 	float2 NCoord=normalize(IN.TexCoord-0.75);
	float CoordLen=length(IN.TexCoord-0.75);
	float PolarAngle=acos(NCoord.x)/3.1416;
	if (NCoord.y<0) { PolarAngle=2.0f-PolarAngle;};
	AngularOffset=PolarAngle-RadialRange*6;
	for (BlurStep=0;BlurStep<13;BlurStep++){
		c+=tex2D(tex,float2(CoordLen*cos(AngularOffset*3.1416),CoordLen*sin(AngularOffset*3.1416))+0.75)*BlurWeights[BlurStep];
		AngularOffset+=RadialRange;
	}; 
 }else if ((IN.TexCoord.x<=0.25)&&(IN.TexCoord.x>=0.125)) {
 AngularOffset=IN.TexCoord.x-AnamorphicRange*6;
 	for (BlurStep=0;BlurStep<13;BlurStep++){
		c+=tex2D(tex,float2(AngularOffset,IN.TexCoord.y))*BlurWeights[BlurStep];
		AngularOffset+=AnamorphicRange;
	}; 
 }else{c=0;};
return c;
};


technique
{
	pass
   
    {		
		VertexShader = compile vs_3_0 VS_Comb();
		PixelShader = compile ps_3_0 PS_Halo(TESR_SourceBuffer);
    }
    	pass
   
    {		
		VertexShader = compile vs_3_0 VS_Comb();
		PixelShader = compile ps_3_0 PS_Reflect(TESR_RenderedBuffer,-0.9, 0.2);
    }
        pass

    {		
		VertexShader = compile vs_3_0 VS_Comb();
		PixelShader = compile ps_3_0 PS_Reflect(TESR_RenderedBuffer,-0.5,0.1);
    }
    pass
    {		
		VertexShader = compile vs_3_0 VS_Comb();
		PixelShader = compile ps_3_0 PS_HeavyBlur(TESR_RenderedBuffer,0.004,0.01);
    }
	pass
	{
		VertexShader = compile vs_3_0 VS_Comb();
		PixelShader = compile ps_3_0 BlurPass( OffsetMaskH );
	}
	
	pass
	{
		VertexShader = compile vs_3_0 VS_Comb();
		PixelShader = compile ps_3_0 BlurPass( OffsetMaskV );
	}
    pass
    {		
		VertexShader = compile vs_3_0 VS_Comb();
		PixelShader = compile ps_3_0 PS_Comb(TESR_RenderedBuffer,TESR_SourceBuffer);
    }
 }