//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  ENBSeries effect file                                               //
//  visit http://enbdev.com for updates                                 //
//  Copyright (c) 2007-2013 Boris Vorontsov                             //
//                                                                      //
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
//                                                                      //
//  Crazy Flare with Weather FX by kingeric1992                         //
//         inspired by John Chapman,    Pseudo Lens Flare               //
//                     Boris Vorontsov, Original enblens.fx             // 
//  for more info, visit                                                //
//    Crazy Flare                                                       // 
//      http://enbseries.enbdev.com/forum/viewtopic.php?f=7&t=3697      //
//    Weather FX                                                        //
//      http://enbseries.enbdev.com/forum/viewtopic.php?f=7&t=3293      //
//                                                                      //
//  update: June 19, 2015                                               //
//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  internal parameters, can be modified                                //
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
//                                                                      //
//  place "//" before "#define" to disable specific feature entirely,   //
//  equivalent to setting effect intensity 0, but save some performance //
//  by skipping computation.                                            //
//                                                                      //
//  example:                                                            //
//      //#define example                                               //
//                                                                      //
//////////////////////////////////////////////////////////////////////////
string enblensInfo="Enblens Weather FX by kingeric1992";
string SkysanVersion="Organic ENB: v0.308.5";

//////////////////////////////////////////////////////////////////////////
//  Global Variables                                                    //
//////////////////////////////////////////////////////////////////////////

//select sampling textures
//SamplerBloom1~ SamplerBloom6, from clear to blur
#define FLARE1_TEXTURE  SamplerBloom2
#define FLARE2_TEXTURE  SamplerBloom3
#define FLARE3_TEXTURE  SamplerBloom3
#define FLARE4_TEXTURE  SamplerBloom3
#define FLARE5_TEXTURE  SamplerBloom3
#define FLARE6_TEXTURE  SamplerBloom3
#define WEATHER_TEXTURE SamplerBloom3

//change weather id according to _weatherlist.ini [WEATHER###]
//for example:
//rain, 62~66 as lvl 1; 67~69 as lvl 2; 70 as lvl 3
#define RAIN_1_START    3
#define RAIN_1_ENDS     4
#define RAIN_2_START    5
#define RAIN_2_ENDS     6
#define RAIN_3_START    90
#define RAIN_3_ENDS     90

//for example:
//snow, 33 as lvl 1; 34,35 as lvl 2; 36 as lvl 3
#define SNOW_1_START    7
#define SNOW_1_ENDS     8
#define SNOW_2_START    91
#define SNOW_2_ENDS     91
#define SNOW_3_START    91
#define SNOW_3_ENDS     91

bool ENABLE_DIRT <
	string UIName =  "Enable lens dirt";
> = {false};
string  LUMA_Info1 = "LUMA: 0=rgb average, 1=Rec.601, 2=Rec.709";
int	LUMA_MODE <
	string UIName="   Luminance weight";
	float UIMin=0;
	float UIMax=2;
> = {0};
string  Chroma_Setting01        		   = "Chroma";
bool	ENABLE_CHROMA		<string UIName="Enable post chromatic aberration";	> = {false};
float   Chroma_Scale        <string UIName="   Chroma_Scale";float UIStep = 0.001; float UIMin=0; > = {0.005}; //Post Chroma strength
float   Chroma_Curve        <string UIName="   Chroma_Curve";                      float UIMin=0; > = {2};     //Post Chroma strength curve from screen center to edge.

#define ALF_SAMPLE              20
string  ALF_Title							  ="Anamorphic Flare";
bool 	ENABLE_ALF	  			<string UIName="Enable ALF effects"; > = {true};
bool 	ALF_SunriseSet_Effect	<string UIName="ALF Sunrise/set effects"; > = {true};
float   ALF_Width     			<string UIName="   ALF_Width"; float UIMax=0.2;float UIMin=0;  > = {0.10};
float   ALF_Curve     			<string UIName="   ALF_Curve";                 float UIMin=0;  > = {3};
float   ALF_Secondary 			<string UIName="   ALF_Secondary";             float UIMin=0;  > = {0.05};
float   ALF_Intensity 			<string UIName="   ALF_Intensity";             float UIMin=0;  > = {1.5};
float3  ALF_Tint      			<string UIName="   ALF_Tint"; string UIWidget="color";         > = {0.25, 0.25, 1};

string  Flare_Settings          = "Flare";
string  Flare_Info1             = "Flare gloabal setting is";
string  Flare_Info2             = "under LENS in enbseries.ini";
bool	ENABLE_FLARE			<string UIName="Enable Flare";  > = {true};
float3	Flare1_Scale			<string UIName="   Flare1 Scale";		string UIWidget="Vector";	float UIStep=0.1;	> = {-0.6, 1.4, -1.0};
float3 	Flare1_Ratio			<string UIName="   Flare1 Ratio";		string UIWidget="Vector";	float UIStep=0.1;	> = {1.0, 1.0, 1.0};
float3 	Flare1_Intensity		<string UIName="   Flare1 Intensity";	string UIWidget="Vector";	float UIStep=0.1;	> = {10, 10, 10};
float3	Flare1_InnerEdge		<string UIName="   Flare1 InnerEdge";	string UIWidget="Vector";	float UIStep=0.1;	> = {0, 0, 0.4};
float3	Flare1_OuterEdge		<string UIName="   Flare1 OuterEdge";	string UIWidget="Vector";	float UIStep=0.1;	> = {0.8, 1.2, 1.2};
float3	Flare1_Distort_Curve	<string UIName="   Flare1 Distort Curve";	string UIWidget="Vector";	float UIStep=0.1;	> = {2.0, 2.0, 2.0};
float3	Flare1_Distort_Scale	<string UIName="   Flare1 Distort Scale";	string UIWidget="Vector";	float UIStep=0.1;	> = {0, -0.2, -0.2};
float3	Flare1_TintX			<string UIName="   Flare1 Tint X";		string UIWidget="color";	> = {1, 0.5, 1};
float3	Flare1_TintY			<string UIName="   Flare1 Tint Y";		string UIWidget="color";	> = {1, 1, 1};
float3	Flare1_TintZ			<string UIName="   Flare1 Tint Z";		string UIWidget="color";	> = {1, 1, 1};
float3	Flare2_Scale			<string UIName="   Flare2 Scale";		string UIWidget="Vector";	float UIStep=0.1;	> = {-1.6, 1.5, -1.0};
float3	Flare2_Ratio			<string UIName="   Flare2 Ratio";		string UIWidget="Vector";	float UIStep=0.1;	> = {1.0, 1.0, 1.0};
float3	Flare2_Intensity		<string UIName="   Flare2 Intensity";	string UIWidget="Vector";	float UIStep=0.1;	> = {10, 10, 10};
float3	Flare2_InnerEdge		<string UIName="   Flare2 InnerEdge";	string UIWidget="Vector";	float UIStep=0.1;	> = {0.2, 0.2, 0.4};
float3	Flare2_OuterEdge		<string UIName="   Flare2 OuterEdge";	string UIWidget="Vector";	float UIStep=0.1;	> = {2.0, 2.0, 2.2};
float3	Flare2_Distort_Curve	<string UIName="   Flare2 Distort Curve";	string UIWidget="Vector";	float UIStep=0.1;	> = {2.0, 2.0, 2.0};
float3	Flare2_Distort_Scale	<string UIName="   Flare2 Distort Scale";	string UIWidget="Vector";	float UIStep=0.1;	> = {-1, -1, -1.2};
float3	Flare2_TintX			<string UIName="   Flare2 Tint X";		string UIWidget="color";	> = {1, 1, 1};
float3	Flare2_TintY			<string UIName="   Flare2 Tint Y";		string UIWidget="color";	> = {1, 0.75, 1};
float3	Flare2_TintZ			<string UIName="   Flare2 Tint Z";		string UIWidget="color";	> = {1, 1, 1};

string  Starburst_Settings      			  ="Starburst";
bool ENABLE_STARBURST			<string UIName="Enable Starburst flare mask"; > = {true};
float   Starburst_Scale         <string UIName="   Starburst_Scale";       float UIMin=0;  > = {0.5};
float   Starburst_Intensity     <string UIName="   Starburst_Intensity";       float UIMin=0;  > = {1.5};
float   Starburst_Curve         <string UIName="   Starburst_Curve";           float UIMin=0;  > = {1.5};
float   Starburst_InnerEdge     <string UIName="   Starburst_InnerEdge";       float UIMax=1;  > = {0.35};
float   Starburst_OuterEdge     <string UIName="   Starburst_OuterEdge";       float UIMin=0;  > = {0.75};

#define WEATHER_RAIN_TYPE       0   //[0,  1], Select rain type, 0== droplets, 1== dynamic lens dirt.
string  Weather_blank           =" ";
string  Weather_Settings        ="Weather FX";
bool 	ENABLE_WEATHER_FX 		<string UIName="Enable weather effects"; > = {true};
string  Rain_Settings           			  ="Rain";
float   Rain_SizeMin            <string UIName="   Rain SizeMin";          float UIMin=0; float UIMax=2;   > = {0.05};
float   Rain_SizeMax            <string UIName="   Rain SizeMax";          float UIMin=0; float UIMax=2;   > = {0.15};
float   Rain_SizeCurve          = 0.25;
float   Rain_Freqency           <string UIName="   Rain Freqency(Hz)";     float UIMin=0; float UIMax=10;  > = {0.8};
float   Rain_Intensity_D        <string UIName="   Rain Intensity-D";      float UIMin=0; float UIMax=100; > = {1};
float   Rain_Intensity_N        <string UIName="   Rain Intensity-N";      float UIMin=0; float UIMax=100; > = {1};
#if     (WEATHER_RAIN_TYPE == 0)
float   Droplet_Offset_Curve    = 1.5;
float   Droplet_Offset_Scale    = 0.5;
int 	WEATHER_DROPLET_GRID	<string UIName="   Droplet Grid Size";     float UIMin=1; float UIStep=1; > = {5}; //5 means it use 5x5 grid with total 25 textures
float   Droplet_Ratio_Min       <string UIName="   Droplet Ratio Min";     float UIMin=0;   > = {0.9};
float   Droplet_Ratio_Max       <string UIName="   Droplet Ratio Max";     float UIMin=0;   > = {1.1};
float2  Droplet_Feather         = {0.25, 1};
#else
int     Dirt_ShutterLeaf        <string UIName="   Shutter Leaf";          float UIMin=5; float UIMax=8;   > = {7};
float   Dirt_ShutterShape       <string UIName="   Shutter Shape";         float UIMin=0; float UIMax=1;   > = {1};
int     Dirt_Angle              <string UIName="   Offset Angle(\xB0)";    float UIMin=0; float UIMax=36;  > = {0};
float   Dirt_Curve_D            <string UIName="   Dirt Curve-D";          float UIMin=0; float UIMax=100; > = {0.5};
float   Dirt_Curve_N            <string UIName="   Dirt Curve-N";          float UIMin=0; float UIMax=100; > = {0.9};
float   Dirt_DestWeight         = 0.2;
#endif
string  Frost_Settings          			  ="Frost";
float   Frost_FeatherRadii      <string UIName="   Frost Feather Radii";   float UIMin=0; float UIMax=0.6; > = {0.15};
float   Frost_MinRadii          <string UIName="   Frost MinRadii";        float UIMin=0; float UIMax=0.6; > = {0.1};
float   Frost_Intensity_D       <string UIName="   Frost Intensity-D";     float UIMin=0; float UIMax=1;   > = {0.6};
float   Frost_Intensity_N       <string UIName="   Frost Intensity-N";     float UIMin=0; float UIMax=1;   > = {0.6};
float   Frost_Frequency         <string UIName="   Frost Frequency(Hz)";   float UIMin=0; float UIMax=2;   > = {0.08};

//////////////////////////////////////////////////////////////////////////
//  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;         //1,2,3,4
float4  tempF2;         //5,6,7,8
float4  tempF3;         //9,0
float4  ScreenSize;     //x=Width, y=1/Width, z=ScreenScaleY, w=1/ScreenScaleY
float   ENightDayFactor;//changes in range 0..1, 0 means that night time, 1 - day time
float   EInteriorFactor;//changes 0 or 1. 0 means that exterior, 1 - interior
float4  Timer;          //x=generic timer in range 0..1, period of 16777216 ms (4.6 hours), w=frame time elapsed (in seconds)
float4  TempParameters; //additional info for computations
float4  LensParameters; //x=reflection intensity, y=reflection power, z=dirt intensity, w=dirt power
float   FieldOfView;    //fov in degrees
float4  WeatherAndTime; //.x - current weather index, .y - outgoing weather index, .z - weather transition, .w - time of the day in 24 standart hours.

texture2D texColor;     //output of Draw
texture2D texMask;      //enblensmask texture
texture2D texBloom1;    //Original ENB blurred input;fullres, output of bloom prepass
texture2D texBloom2;    //Downsampled to 512
texture2D texBloom3;    //Downsampled to 256
texture2D texBloom4;    //Downsampled to 128
texture2D texBloom5;    //Downsampled to 64
texture2D texBloom6;    //Downsampled to 32
texture2D texBloom7;    //empty
texture2D texBloom8;    //empty

texture2D texWeather    <string ResourceName="enbweather.bmp"; >;//.rgb is droplet normal map, .a is frost mask
sampler2D SamplerWeather = sampler_state
{
    Texture = <texWeather>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = NONE;
    AddressU  = Clamp;
    AddressV  = Clamp;
    SRGBTexture = FALSE;
    MaxMipLevel = 0;
    MipMapLodBias = 0;
};

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

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

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

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

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

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

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

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

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

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

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

struct VS_OUTPUT_WEATHER
{
    float4 vpos     : POSITION;
    float2 txcoord0 : TEXCOORD0;
    float3 wconst   : TEXCOORD1;
};

//////////////////////////////////////////////////////////////////////////
//  Funstions                                                           //
//////////////////////////////////////////////////////////////////////////

float   Lum(float3 color)
{
	float3 luma_value = float3(0.333, 0.333, 0.333);
	if(LUMA_MODE == 1) {
		luma_value = float3(0.299, 0.587, 0.114);
	}
	if(LUMA_MODE == 2) {
		luma_value = float3(0.2126, 0.7152, 0.0722);
	}
    return dot(color, luma_value);
	
}

float2 Distort( float2 coord, float curve, float scale)
{
    float2 dist   = coord - 0.5;
    float  r      = length(float2( dist.x * ScreenSize.z, dist.y));
    float2 offset = pow( 2 * r, curve) * (dist / r) * scale;
    
    return coord + offset;
}

//temp.x == curve, .y == scale
float4 Chroma( sampler2D inputtex, float2 coord, float2 temp)
{
    float4 res = 0;
    res.r  = tex2D(inputtex, Distort(coord, temp.x, temp.y)).r;
    res.ga = tex2D(inputtex, coord).ga;
    res.b  = tex2D(inputtex, Distort(coord, temp.x, -temp.y)).b;
    return res;
}

float   Random(float2 co)
{
    return frac(sin(dot(co.xy, float2(12.9898, 78.233))) * 43758.5453);
}

//////////////////////////////////////////////////////////////////////////
//  Shaders                                                             //
//////////////////////////////////////////////////////////////////////////
// Dynamic Lens Dirt(rainFX) VS
//seed.xy == offset; .z == size; .w == ratio
VS_OUTPUT_WEATHER VS_Rain(VS_INPUT_POST IN, uniform float4 seed, uniform float toffset)
{
    VS_OUTPUT_WEATHER OUT;  

    float2 rainlvl;
    if(WeatherAndTime.x > (RAIN_1_START - 0.2) && WeatherAndTime.x < (RAIN_1_ENDS + 0.2))
        rainlvl.x = 1;
    else if(WeatherAndTime.x > (RAIN_2_START - 0.2) && WeatherAndTime.x < (RAIN_2_ENDS + 0.2))
        rainlvl.x = 2;
    else if(WeatherAndTime.x > (RAIN_3_START - 0.2) && WeatherAndTime.x < (RAIN_3_ENDS + 0.2))
        rainlvl.x = 3;
    else
        rainlvl.x = 0;
    
    if(WeatherAndTime.y > (RAIN_1_START - 0.2) && WeatherAndTime.y < (RAIN_1_ENDS + 0.2))
        rainlvl.y = 1;
    else if(WeatherAndTime.y > (RAIN_2_START - 0.2) && WeatherAndTime.y < (RAIN_2_ENDS + 0.2))
        rainlvl.y = 2;
    else if(WeatherAndTime.y > (RAIN_3_START - 0.2) && WeatherAndTime.y < (RAIN_3_ENDS + 0.2))
        rainlvl.y = 3;
    else
        rainlvl.y = 0;
    
    rainlvl /= 3;
    rainlvl *= (1 - EInteriorFactor);
    
    float  frequency = lerp( 0, Rain_Freqency, lerp(rainlvl.x, rainlvl.y, step(WeatherAndTime.z, 0.5)));
    float  time      = (Timer.x * 16777.216 + toffset) * frequency;
    float2 timeconst = float2(floor(time), frac(time));
    float  random    = Random( float2(timeconst.x, seed.z));       
    float  size      = lerp( Rain_SizeMin, Rain_SizeMax, pow(random, lerp(1, Rain_SizeCurve, rainlvl.y)));
    float2 offset    = float2( Random( float2(timeconst.x, seed.x)), Random( float2(timeconst.x, seed.y))) * 2 - 1;
    float  angle     = Random(float2(timeconst.x, seed.y)) * 6.28;
    size            *= 1 + timeconst.y * 0.2;//enlarge
#if (WEATHER_RAIN_TYPE == 0)
    float  ratio     = lerp(Droplet_Ratio_Min, Droplet_Ratio_Max, Random(float2(timeconst.x, seed.w)));
    float2 rotate;
    sincos(angle, rotate.y, rotate.x);
    float2 pos       = IN.pos.xy * size * float2(ratio, ScreenSize.z);
    pos = float2( dot(pos, rotate * float2( 1, -1)), dot(pos, rotate.yx));
#else
    float2 pos       = IN.pos.xy * size * float2(1, ScreenSize.z);
#endif
    OUT.vpos         = float4(pos - offset, IN.pos.z, 1.0);;
    OUT.txcoord0.xy  = IN.txcoord0.xy;
    OUT.wconst       = (frequency > 0 )? pow( 1 - timeconst.y, 0.3) * (abs(WeatherAndTime.z - 0.5) * 2): 0; //Alpha, fades during transition  
    OUT.wconst.x     = timeconst;
    OUT.wconst.y     = angle;
    return OUT;
}
#if (WEATHER_RAIN_TYPE == 0)
// Droplets(rainFX) PS
float4 PS_Droplets(VS_OUTPUT_WEATHER IN, float2 vPos : VPOS, uniform float2 seed) : COLOR
{
	clip(!ENABLE_WEATHER_FX ? -1 : 1 );  // just exit if WEATHER is not enabled

    clip((IN.wconst.z < 0.001)? -1:1 );//discard if weather constant == 0
    float2 coord = IN.txcoord0.xy;
    float2 sscoord = ScreenSize.y * vPos;
    sscoord.y *= ScreenSize.z;  

    float  intensity = lerp(Rain_Intensity_N, Rain_Intensity_D, ENightDayFactor);
    
    float2 index = float2(Random(float2(IN.wconst.x, seed.x)), Random(float2(IN.wconst.x, seed.y)));
    index *= WEATHER_DROPLET_GRID;
    index  = floor(index) + coord;

    float3 normal = tex2D(SamplerWeather, index / WEATHER_DROPLET_GRID).rgb - 0.5;
    normal *= 2;
    normal.xy = normalize(normal.xy) * pow(length(normal.xy), Droplet_Offset_Curve);
    
    float2 rotate;
    sincos(-IN.wconst.y, rotate.y, rotate.x);
    normal.xy = float2( dot(normal.xy, rotate * float2( 1, -1)), dot(normal.xy, rotate.yx));

    float4 res = tex2D(WEATHER_TEXTURE, sscoord + normal.xy * Droplet_Offset_Scale);
    res.a = IN.wconst.z * smoothstep(Droplet_Feather.x, Droplet_Feather.y, normal.z);
	res.rgb *= intensity * res.a;
    res.a   *= 0.75;
    return res;
}
#else
// Dynamic Lens Dirt(rainFX) PS
float4 PS_Rain(VS_OUTPUT_WEATHER IN, float2 vPos : VPOS) : COLOR
{
	clip(!ENABLE_WEATHER_FX ? -1 : 1 );  // just exit if WEATHER is not enabled

    clip((IN.wconst.z < 0.001)? -1:1 );//discard if weather constant == 0
    
    float2 coord     = IN.txcoord0.xy - 0.5;
    float2 pixelSize = ScreenSize.y;
    pixelSize.y     *= ScreenSize.z;
    float  theta     = ( length(coord) == 0)? 0 : atan2(coord.y, coord.x) + 3.1415926;
    float  leaf      = 6.28318530 / Dirt_ShutterLeaf;
    float  delta     = (theta + Dirt_Angle) % leaf;
    delta           -= leaf * 0.5;
    float  r         = lerp(1, cos(leaf * 0.5) / cos(delta), Dirt_ShutterShape) * 0.5;
    
    float  intensity = lerp(Rain_Intensity_N, Rain_Intensity_D, ENightDayFactor);
    float  curve     = lerp(Dirt_Curve_N, Dirt_Curve_D, ENightDayFactor);
    
    //Lens Dirt coloring by Boris
    float4 templens  = tex2D(SamplerBloom6, vPos * pixelSize);
    float  maxlens   = max(templens.r, max( templens.g, templens.b));
    float  tempnor   = maxlens / ( 1.0 + maxlens);
    templens.rgb    *= pow(tempnor, curve) * intensity * IN.wconst.z;
    templens.a       = lerp(IN.wconst.z, 0, Dirt_DestWeight);
    templens        *= 1 - smoothstep(r - 0.1, r,length(coord));
    return templens;
}
#endif
// Frost vignette VS
VS_OUTPUT_WEATHER VS_Snow(VS_INPUT_POST IN)
{
    VS_OUTPUT_WEATHER OUT;

    float2 lvl;
    if(WeatherAndTime.x > (SNOW_1_START - 0.2) && WeatherAndTime.x < (SNOW_1_ENDS + 0.2))
        lvl.x = 1;
    else if(WeatherAndTime.x > (SNOW_2_START - 0.2) && WeatherAndTime.x < (SNOW_2_ENDS + 0.2))
        lvl.x = 2;
    else if(WeatherAndTime.x > (SNOW_3_START - 0.2) && WeatherAndTime.x < (SNOW_3_ENDS + 0.2))
        lvl.x = 3;
    else
        lvl.x = 0;
        
    if(WeatherAndTime.y > (SNOW_1_START - 0.2) && WeatherAndTime.y < (SNOW_1_ENDS + 0.2))
        lvl.y = 1;
    else if(WeatherAndTime.y > (SNOW_2_START - 0.2) && WeatherAndTime.y < (SNOW_2_ENDS + 0.2))
        lvl.y = 2;
    else if(WeatherAndTime.y > (SNOW_3_START - 0.2) && WeatherAndTime.y < (SNOW_3_ENDS + 0.2))
        lvl.y = 3;
    else
        lvl.y = 0;
        
    lvl.xy /= 3;
    lvl    *= (1 - EInteriorFactor);
        
    OUT.vpos        = float4(IN.pos.x, IN.pos.y, IN.pos.z, 1.0);
    OUT.txcoord0.xy = IN.txcoord0.xy + TempParameters.xy;
    OUT.wconst      = lerp(lvl.y, lvl.x, WeatherAndTime.z);
    
    return OUT;
}

// Frost vignette PS
float4 PS_Frost(VS_OUTPUT_WEATHER IN, float2 vPos : VPOS) : COLOR
{
	clip(!ENABLE_WEATHER_FX ? -1 : 1 );  // just exit if WEATHER is not enabled

    clip((IN.wconst.x < 0.001)? -1:1 );//discard if weather constant == 0
    float  r          = length(IN.txcoord0.xy - 0.5);   
    float4 res        = tex2D(SamplerBloom6, IN.txcoord0.xy);
    float4 frostmask  = tex2D(SamplerWeather, IN.txcoord0.xy).a;
    float  frostradii = lerp( 0.7071, Frost_MinRadii, IN.wconst.x);
    float  intensity  = lerp(Frost_Intensity_N, Frost_Intensity_D, ENightDayFactor);
    
    res   += frostmask * intensity * smoothstep( frostradii, 0.7071, r);
    res.a *= smoothstep( frostradii + Frost_FeatherRadii * (sin(Timer.x * 105360.91648 * Frost_Frequency) + 1) * 0.2, frostradii + Frost_FeatherRadii, r);
    
    return res;
}

//flare.x == scale, flare.y == ratio
VS_OUTPUT_POST VS_Draw(VS_INPUT_POST IN, uniform float2 flare)
{
    VS_OUTPUT_POST OUT;
    OUT.vpos        = float4(IN.pos.xyz, 1.0);
    OUT.vpos.xy    *= flare.x;
    OUT.vpos.x     *= flare.y;
    OUT.txcoord0.xy = IN.txcoord0.xy + TempParameters.xy;//1.0/(bloomtexsize*2.0)
    return OUT;
}

//ALF + Dirt, FullScreen, reduced res
float4 PS_Draw(VS_OUTPUT_POST IN) : COLOR
{
    float2 coord = IN.txcoord0;
    float4 res   = 0;
  if(ENABLE_DIRT) {
    float3 dirt   = tex2D(SamplerBloom6, coord).rgb;
    float3 mask   = tex2D(SamplerMask, coord).rgb;
    float  normal = max(dirt.x, max(dirt.y, dirt.z));
    normal = pow( normal / ( 1.0 + normal), LensParameters.w);
    res.rgb += mask * dirt * normal * LensParameters.z;
  }  //Lens Dirt

//ALF Starts
	if(ENABLE_ALF) {
		for(int i=0; i < ALF_SAMPLE; i++)
		{
			float2 offset = float2(i - (ALF_SAMPLE - 1) * 0.5, 0) * ALF_Width;
			offset+= coord;
			float  normal = (abs(offset.x - 0.5) > 0.5)? 0:1;
			res.a += pow(Lum(tex2D(SamplerBloom1, offset).rgb), ALF_Curve) * normal;
		}
		res.a /= ALF_SAMPLE;
	}
//ALF ENDs

	return res;
}

//flare PS with distortion, center/edge vignette
//distortion.x == curve, .y == scale, .z == inner edge, .w == outer edge
float4 PS_Flare(VS_OUTPUT_POST IN, uniform sampler2D inputtex, uniform float4 tint, uniform float4 flare) : COLOR
{
	clip(!ENABLE_FLARE ? -1 : 1); // just exit if FLARE is not enabled
	
	float nightOffset = (EInteriorFactor ? 1.0 : (1 - ENightDayFactor));
    float2 coord = Distort(IN.txcoord0.xy, flare.x, flare.y);
    float4 res   = tex2D(inputtex, coord);

	res.a    = max( res.r, max( res.g, res.b));//normal weight
	res.a    = pow( res.a / ( 1.0 + res.a), LensParameters.y);
	coord    = IN.txcoord0.xy;
	coord   -= 0.5;
	coord.y *= ScreenSize.w;
	coord.y  = length(coord) * 2;
	res.rgb *= smoothstep(flare.z, 1, coord.y);//center vignette
	res.rgb *= 1 - smoothstep(0, flare.w, coord.y);//edge vignette
	res.rgb *= res.a * tint.rgb * (LensParameters.x * nightOffset) * tint.a;//intensity

    return res;
}

//Post Process, Chromatic, Starburst, ALF
float4  PS_PostProcess(VS_OUTPUT_POST IN) : COLOR
{
    float2 coord = IN.txcoord0.xy;
    float4 res = tex2D(SamplerColor, coord);
    
	if(ENABLE_CHROMA) {
		res = Chroma(SamplerColor, coord, float2(Chroma_Curve, Chroma_Scale));
	} //Chromatic Aberration
    
	float nightOffset = (EInteriorFactor ? 1.0 : (1 - ENightDayFactor));
	if(ENABLE_STARBURST) {
		float alpha;
		float dist   = length((coord - 0.5) * float2(1, ScreenSize.w)) * 2;
		float weight = smoothstep(Starburst_InnerEdge, 1, dist);
		weight  *= 1 - smoothstep(0, Starburst_OuterEdge, dist);
		coord    = Distort(0.5 + (coord - 0.5) * Starburst_Scale, 0, 1);
		alpha    = Lum(tex2D(SamplerBloom1, coord).rgb);
		coord    = float2( coord.x - coord.y, coord.x + coord.y - 1) * 0.7071 + 0.5; //rotate 45 degree
		alpha   -= Lum(tex2D(SamplerBloom1, coord).rgb);
		res.rgb *= 1.0 + pow(abs(alpha), Starburst_Curve) * (Starburst_Intensity * nightOffset) * 1000 * weight;
	}  //Starburst

    res.rgb  = max( min( res.rgb, 32768.0), 0.0);

//ALF Starts
	if(ENABLE_ALF) {
		res.a = 0;
		coord = IN.txcoord0.xy;
		for(int i=0; i < ALF_SAMPLE; i++)
		{
			float2 offset = float2(i - (ALF_SAMPLE - 1) * 0.5, 0) * ALF_Width / ALF_SAMPLE;
			offset+= coord;
			float weight = (abs(offset.x - 0.5) > 0.5)? 0:1;
			res.a += tex2D(SamplerColor, offset).a * weight;
			res.a += tex2D(SamplerColor, 1 - offset).a * ALF_Secondary * weight;
		}
		res.a /= ALF_SAMPLE;
		if(!EInteriorFactor && ALF_SunriseSet_Effect) {
			if(WeatherAndTime.w > 6.5 && WeatherAndTime.w < 7.5) {
				nightOffset +=  (WeatherAndTime.w - 6.5) / 1.5;
			}
			if(WeatherAndTime.w > 7.5 && WeatherAndTime.w < 8.5) {
				nightOffset +=  (1.0 - (WeatherAndTime.w - 7.5)) / 1.5;
			}
			if(WeatherAndTime.w > 17.5 && WeatherAndTime.w < 18.5) {
				nightOffset +=  (WeatherAndTime.w - 17.5) / 1.5;
			}
			if(WeatherAndTime.w > 18.5 && WeatherAndTime.w < 19.5) {
				nightOffset +=  (1.0 - (WeatherAndTime.w - 18.5)) / 1.5;
			}
		}
		res.rgb += (tex2D(SamplerBloom4, coord).rgb + tex2D(SamplerBloom2, coord).rgb) * res.a * ALF_Tint * (ALF_Intensity * nightOffset);
	}
//ALF ENDs

    return res;
}

//////////////////////////////////////////////////////////////////////////
//  Passes                                                              //
//////////////////////////////////////////////////////////////////////////

//actual computation, draw all effects to small texture
technique Draw
{
    pass p0
    {
        VertexShader = compile vs_3_0 VS_Draw(float2(1, 1));
        PixelShader  = compile ps_3_0 PS_Draw();
        
        ColorWriteEnable=RED|GREEN|BLUE|ALPHA;
        DitherEnable=FALSE;
        ZEnable=FALSE;
        CullMode=NONE;
        ALPHATESTENABLE=FALSE;
        SEPARATEALPHABLENDENABLE=FALSE;
        StencilEnable=FALSE;
        FogEnable=FALSE;
        SRGBWRITEENABLE=FALSE;
    }

    pass p1
    {
        VertexShader = compile vs_3_0 VS_Draw((ENABLE_FLARE ? float2(Flare1_Scale.x, Flare1_Ratio.x) : float2(1, 1)));
        PixelShader  = compile ps_3_0 PS_Flare(FLARE1_TEXTURE, float4(Flare1_TintX, Flare1_Intensity.x), 
                        float4(Flare1_Distort_Curve.x, Flare1_Distort_Scale.x, Flare1_InnerEdge.x, Flare1_OuterEdge.x));

        AlphaBlendEnable=TRUE;
        SrcBlend=ONE;
        DestBlend=ONE;
        ColorWriteEnable=RED|GREEN|BLUE;//warning, no alpha output!
        DitherEnable=FALSE;
        ZEnable=FALSE;
        CullMode=NONE;
        ALPHATESTENABLE=FALSE;
        SEPARATEALPHABLENDENABLE=FALSE;
        StencilEnable=FALSE;
        FogEnable=FALSE;
        SRGBWRITEENABLE=FALSE;
    }

    pass p2
    {
        VertexShader = compile vs_3_0 VS_Draw((ENABLE_FLARE ? float2(Flare1_Scale.y, Flare1_Ratio.y) : float2(1, 1)));
        PixelShader  = compile ps_3_0 PS_Flare(FLARE2_TEXTURE, float4(Flare1_TintY, Flare1_Intensity.y), 
                        float4(Flare1_Distort_Curve.y, Flare1_Distort_Scale.y, Flare1_InnerEdge.y, Flare1_OuterEdge.y));
    }

    pass p3
    {
        VertexShader = compile vs_3_0 VS_Draw((ENABLE_FLARE ? float2(Flare1_Scale.z, Flare1_Ratio.z) : float2(1, 1)));
        PixelShader  = compile ps_3_0 PS_Flare(FLARE3_TEXTURE, float4(Flare1_TintZ, Flare1_Intensity.z), 
                        float4(Flare1_Distort_Curve.z, Flare1_Distort_Scale.z, Flare1_InnerEdge.z, Flare1_OuterEdge.z));
    }

    pass p4
    {
        VertexShader = compile vs_3_0 VS_Draw((ENABLE_FLARE ? float2(Flare2_Scale.x, Flare2_Ratio.x) : float2(1, 1)));
        PixelShader  = compile ps_3_0 PS_Flare(FLARE4_TEXTURE, float4(Flare2_TintX, Flare2_Intensity.x), 
                        float4(Flare2_Distort_Curve.x, Flare2_Distort_Scale.x, Flare2_InnerEdge.x, Flare2_OuterEdge.x));
    }

    pass p5
    {
        VertexShader = compile vs_3_0 VS_Draw((ENABLE_FLARE ? float2(Flare2_Scale.y, Flare2_Ratio.y) : float2(1, 1)));
        PixelShader  = compile ps_3_0 PS_Flare(FLARE5_TEXTURE, float4(Flare2_TintY, Flare2_Intensity.y), 
                        float4(Flare2_Distort_Curve.y, Flare2_Distort_Scale.y, Flare2_InnerEdge.y, Flare2_OuterEdge.y));
    }

    pass p6
    {
        VertexShader = compile vs_3_0 VS_Draw((ENABLE_FLARE ? float2(Flare2_Scale.z, Flare2_Ratio.z) : float2(1, 1)));
        PixelShader  = compile ps_3_0 PS_Flare(FLARE6_TEXTURE, float4(Flare2_TintZ, Flare2_Intensity.z), 
                        float4(Flare2_Distort_Curve.z, Flare2_Distort_Scale.z, Flare2_InnerEdge.z, Flare2_OuterEdge.z));
    }

}

//final pass, output to screen with additive blending and no alpha
technique LensPostPass
{
    pass p0
    {
        VertexShader = compile vs_3_0 VS_Draw(float2(1, 1));
        PixelShader  = compile ps_3_0 PS_PostProcess();

        AlphaBlendEnable=TRUE;
        SrcBlend=ONE;
        DestBlend=ONE;
        ColorWriteEnable=RED|GREEN|BLUE;//warning, no alpha output!
        DitherEnable=FALSE;
        ZEnable=FALSE;
        CullMode=NONE;
        ALPHATESTENABLE=FALSE;
        SEPARATEALPHABLENDENABLE=FALSE;
        StencilEnable=FALSE;
        FogEnable=FALSE;
        SRGBWRITEENABLE=FALSE;
    }

    pass p1
    {
        VertexShader = compile vs_3_0 VS_Rain(ENABLE_WEATHER_FX ? float4(72, 11, 19, 5) : float4(1,1,1,1), ENABLE_WEATHER_FX ? 1.7 : 0);
#if (WEATHER_RAIN_TYPE == 0)
        PixelShader  = compile ps_3_0 PS_Droplets(float2(3, 5));
#else
        PixelShader  = compile ps_3_0 PS_Rain();
#endif
        AlphaBlendEnable=TRUE;
        SrcBlend=ONE;
        DestBlend=INVSRCALPHA;
        ColorWriteEnable=RED|GREEN|BLUE;//warning, no alpha output!
        CullMode=NONE;
        AlphaTestEnable=FALSE;
        SeparateAlphaBlendEnable=FALSE;
        SRGBWriteEnable=FALSE;
    }
    pass p2
    {
        VertexShader = compile vs_3_0 VS_Rain(ENABLE_WEATHER_FX ? float4(88, 3, 500, 11) : float4(1,1,1,1), ENABLE_WEATHER_FX ? 2.9 : 0);
#if (WEATHER_RAIN_TYPE == 0)       
        PixelShader  = compile ps_3_0 PS_Droplets(float2(2, 7));
#else
        PixelShader  = compile ps_3_0 PS_Rain();
#endif
    }
    
    pass p3
    {
        VertexShader = compile vs_3_0 VS_Rain(ENABLE_WEATHER_FX ? float4(20, 100, 700, 9) : float4(1,1,1,1), ENABLE_WEATHER_FX ? 3.7 : 0);
#if (WEATHER_RAIN_TYPE == 0)      
        PixelShader  = compile ps_3_0 PS_Droplets(float2(11, 13));
#else
        PixelShader  = compile ps_3_0 PS_Rain();
#endif
    }
    
    pass p4
    {
        VertexShader = compile vs_3_0 VS_Rain(ENABLE_WEATHER_FX ? float4(150, 3, 250, 7) : float4(1,1,1,1), ENABLE_WEATHER_FX ? 1.3 : 0);
#if (WEATHER_RAIN_TYPE == 0)      
        PixelShader  = compile ps_3_0 PS_Droplets(float2(17, 19));
#else
        PixelShader  = compile ps_3_0 PS_Rain();
#endif
    }
    
    pass p5
    {
        VertexShader = compile vs_3_0 VS_Rain(ENABLE_WEATHER_FX ? float4(66, 220, 250, 19) : float4(1,1,1,1), 0);
#if (WEATHER_RAIN_TYPE == 0)       
        PixelShader  = compile ps_3_0 PS_Droplets(float2(23, 29));
#else
        PixelShader  = compile ps_3_0 PS_Rain();
#endif
    }
    
    pass p6
    {
        VertexShader = compile vs_3_0 VS_Snow();
        PixelShader  = compile ps_3_0 PS_Frost();

        AlphaBlendEnable=TRUE;
        SrcBlend=SRCALPHA;
        DestBlend=INVSRCALPHA;
        ColorWriteEnable=RED|GREEN|BLUE;//warning, no alpha output!
        CullMode=NONE;
        AlphaTestEnable=FALSE;
        SeparateAlphaBlendEnable=FALSE;
        SRGBWriteEnable=FALSE;
    }    

}