//
// Improved Water Shader v0.6 for MGE 3.8.1  by phal
//

///////////////////////////////////////////////////////////////////////////////////////
   //
   // SETTINGS:
   //

   // Change the following value to 1 to enable blurred water reflections.
   // Enabling this setting might cause an FPS hit.
#define WATERBLUR 	0

   // Change the following value to adjust caustic lighting intensity in percent.
   // Default: 50. This value should be between 1 and 100. Set to 0 to disable caustics.
#define CAUSTICINT 	50

   // Change the following value to 1 to use an alternative exponential fog formula.
   // When using exponential fog, I recommend to increase the distant land draw distance
   // in MGE gui in the 'Distant Land' tab to about four times the 'Above Water Fog End'
   // range. This will prevent popping in of distant mountains. Distant static range does 
   // not need to be increased.
   // Enabling this setting might cause an FPS hit.
#define EXPFOG 		0

   //
   // END OF SETTINGS
   //
///////////////////////////////////////////////////////////////////////////////////////



//Original by Timeslip //mods by harlanrm
Matrix TexProj;
//Matrix worldviewproj;
Matrix view;
Matrix proj;
Matrix world;
float4x4 MatrixPalette[4] : MATRIXPALETTE;
float3 SunVec;
float3 SunCol;
float3 EyePos;
float3 SunAmb;
float3 SkyCol;
float ticks;
float2 offset;
float TexBlend;
float2 rcpres;
int FogCol;
float3 FogCol2;
float FogStart;
float FogRange;
float BlendStart;
float BlendEnd;
float GrassDist;
float2 WindVec;
float PixelWidth;
float PixelHeight;
float WaterLevel = 0;
float3 SunPos;
float SunVis;

texture tex0;
texture tex1;
texture tex2;
texture tex3;
texture tex4;
sampler s0 = sampler_state { texture = <tex0>; minfilter = linear; magfilter = linear; mipfilter = linear; addressu=clamp; addressv = clamp; };
sampler s1 = sampler_state { texture = <tex1>; minfilter = linear; magfilter = linear; mipfilter = linear; addressu=wrap; addressv = wrap; };
sampler s2 = sampler_state { texture = <tex2>; minfilter = linear; magfilter = linear; mipfilter = linear; addressu=wrap; addressv = wrap; };
sampler s3 = sampler_state { texture = <tex3>; minfilter = linear; magfilter = linear; mipfilter = linear; addressu=wrap; addressv = wrap; };
sampler s4 = sampler_state { texture = <tex3>; minfilter = linear; magfilter = linear; mipfilter = linear; addressu=clamp; addressv = clamp; };

//For sampling the far water texture
sampler s5 = sampler_state { texture = <tex1>; minfilter = linear; magfilter = linear; mipfilter = none; addressu=wrap; addressv = wrap; };
sampler s6 = sampler_state { texture = <tex2>; minfilter = linear; magfilter = linear; mipfilter = none; addressu=wrap; addressv = wrap; };

sampler s7 = sampler_state { texture = <tex4>; minfilter = linear; magfilter = linear; mipfilter = linear; addressu=clamp; addressv = clamp; };

//static const float3 watercolour = { 0.9, 0.9, 1 };//original //wasn't used previously

static const float3 watercolour = { 0.4, 0.45, 0.5 };
//static const float FLT_MAX = 3.402823466e+38F;
static const float FLT_MAX = 340282346600000000000000000000000000000.0f;

/*
static const float4x4 TexProj = {
	0.5, 0.0, 0.0, 0.5,
	0.0, 0.5, 0.0, 0.5,
	0.0, 0.0, 0.5, 0.5,
	0.0, 0.0, 0.0, 1.0
};
*/

/////////////////////////////////////////////////////
//  Global calculations for improved water shader  //
/////////////////////////////////////////////////////

static const float _lightfactor = 1-pow(1-SunVis,2);
static const float _windfactor = length(WindVec)+0.2;
static const float3 SunCollf = SunCol * _lightfactor;
static const float3 _depthcolor = SunCollf*float3(0.04,0.06,0.08) + (SkyCol+FogCol2)*(0.08).xxx;

static const float cauststr = 0.01699 * CAUSTICINT *_lightfactor;

static const float FogRangeMinusStart = FogRange - FogStart;
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////

#if EXPFOG == 1
	static const float ExpFogStart = max(0, FogStart);
	static const float ExpFogMult = saturate( FogRange/(FogRange-FogStart) );
	static const float ExpFogRangeMinusStart = FogRange - ExpFogStart;
	float3 skyfogblend(float z)
	{
		return (   1 - pow(1-saturate( 2.22*saturate(z-0.075) ), 1.15)   ).xxx;
	}
	float getFog(float dist)
	{
		return saturate( exp(-(dist-ExpFogStart)/(ExpFogRangeMinusStart)) ) * ExpFogMult;
	}
#endif
	
float4 RenderShader( in float2 TexCoords : TEXCOORD0, in float3 Light : TEXCOORD1, in float4 Height : TEXCOORD2) : COLOR0
{
	clip(Height);
	float3 Result = tex2D( s3, TexCoords) * Light;
	return float4(Result, 1);
}

struct StatVertIn {
	float4 pos : POSITION;
	float3 normal : NORMAL;
	float4 color : COLOR0;
	float2 texcoords : TEXCOORD0;
};

struct StatVertOut {
	float4 pos : POSITION;
	float2 texcoords : TEXCOORD0;
	float3 color : TEXCOORD1;
	float3 normal : TEXCOORD2;

#if EXPFOG == 1
	float4 fog : TEXCOORD3;
#else
	float fog : TEXCOORD3;
#endif	

	float4 screenpos: TEXCOORD4;
	float blend : TEXCOORD5;
};

StatVertOut StaticVS( StatVertIn IN ) {
	StatVertOut OUT;
	
	OUT.texcoords = IN.texcoords;
	
	//Define % to Fog
	float4 worldpos = mul(IN.pos, world);
	
#if EXPFOG == 1
	float3 EyeVec = worldpos.xyz - EyePos.xyz;
	float dist = length(EyeVec);
	EyeVec /= dist;
	OUT.fog = float4(lerp(FogCol2,SkyCol, skyfogblend(EyeVec.z)), getFog(dist) );
#else
	float dist = length(worldpos.xyz - EyePos.xyz);
	OUT.fog = saturate( (FogRange - dist) / (FogRangeMinusStart) );	
#endif	

	//Define % to Blend
	OUT.blend = saturate( (BlendEnd - dist) / (BlendEnd-BlendStart) );

	//Projection
	OUT.pos = mul(worldpos, view);
	OUT.pos = mul(OUT.pos, proj);
		
	//Texture Projection
	OUT.screenpos = mul( worldpos, TexProj );

	//Lighting
	OUT.normal = normalize( IN.normal * 2 - 1 ); //Decompress
	OUT.normal = normalize( mul(OUT.normal, (float3x3)world) ); //Rotate normals but don't translate them
	OUT.color = IN.color;
		
	return OUT;
}

struct StatInstVertIn {
	float4 pos : POSITION;
	float3 normal : NORMAL;
	float4 color : COLOR0;
	float2 texcoords : TEXCOORD0;
	float4 m1 : TEXCOORD1;
	float4 m2 : TEXCOORD2;
	float4 m3 : TEXCOORD3;
	float4 m4 : TEXCOORD4;
};

StatVertOut StaticInstVS( StatInstVertIn IN ) {
	StatVertOut OUT;
	
	OUT.texcoords = IN.texcoords;
	
	//Pack instance transform
    float4x4 worldmat = float4x4(IN.m1, IN.m2, IN.m3, IN.m4);

	//Define % to Fog
	float4 worldpos = mul(IN.pos, worldmat);
	
#if EXPFOG == 1
	float3 EyeVec = worldpos.xyz - EyePos.xyz;
	float dist = length(EyeVec);
	EyeVec /= dist;
	OUT.fog = float4(lerp(FogCol2,SkyCol, skyfogblend(EyeVec.z)), getFog(dist) );
#else
	OUT.fog = saturate( (FogRange - length(worldpos.xyz - EyePos.xyz) ) / (FogRangeMinusStart) );
#endif	

	//Projection
	OUT.pos = mul(worldpos, view);
	OUT.pos = mul(OUT.pos, proj);
	
	//Lighting
	OUT.normal = normalize( mul(IN.normal, (float3x3)worldmat) );
	OUT.color = IN.color;
	
	OUT.screenpos = 0;
	OUT.blend = 0;
	
	return OUT;
}

float4 StaticPS( StatVertOut IN ) : COLOR0 {
	//clip(IN.height - WaterLevel);
	float4 Result = tex2D( s3, IN.texcoords);
	clip(Result.a - 0.5);
	
	//Lighting
	//float3 diffuse = saturate(dot(IN.normal,-SunVec)) * SunCol;
	//float3 ambient = SunAmb;
	
	//Result.rgb *= (diffuse + ambient) * IN.color;
	
	//Lighting
	float3 normal = normalize(IN.normal);
	Result.rgb *= saturate( (saturate(dot(-SunVec,normal)) * SunCol * IN.color) + (SunAmb * IN.color) );
	
	//Fogging
#if EXPFOG == 1
	Result.rgb = lerp(IN.fog.rgb, Result.rgb, IN.fog.a);
#else
	Result.rgb = lerp(FogCol2, Result.rgb, IN.fog);
#endif	

	
	//Blending
	float3 background = tex2Dproj(s0, IN.screenpos).rgb;
	Result.rgb = lerp( background, Result.rgb, IN.blend);

#if EXPFOG == 1
	return float4(Result.rgb, 1 - IN.fog.a);
#else
	return float4(Result.rgb, 1 - IN.fog);
#endif	
}

struct StatRefVertOut {
	float4 pos : POSITION;
	float2 texcoords : TEXCOORD0;
	float3 color : TEXCOORD1;
	float3 normal : TEXCOORD2;
	float fog : TEXCOORD3;
	float height : TEXCOORD6;
};

StatRefVertOut StaticReflectionVS( StatVertIn IN ) {
	StatRefVertOut OUT;
	
	OUT.texcoords = IN.texcoords;
	
	float4 worldpos = mul(IN.pos, world);
	
	//Define % to 	Fog
	float3 EyeVec = worldpos.xyz - float3(EyePos.xy,2*WaterLevel-EyePos.z);
	float dist = length(EyeVec);
	EyeVec /= dist;
	
	//Define % to Fog
#if EXPFOG == 1
	OUT.fog = saturate( exp(-(max(0,worldpos.z)/(0.0001+saturate(EyeVec.z)))/ExpFogRangeMinusStart) );
#else
	OUT.fog = 	saturate(
					saturate( (FogRange - dist ) / (FogRangeMinusStart) ) /
					(0.001 + saturate( (FogRange - (EyePos.z-WaterLevel)/(0.001+saturate(EyeVec.z)) ) / (FogRangeMinusStart) ))
				);
#endif	
	
	//OUT.fog = saturate( (FogRange -  dist) / (FogRangeMinusStart) );
	
	//Projection
	OUT.pos = mul(worldpos, view);
	OUT.pos = mul(OUT.pos, proj);

	//Lighting
	OUT.normal = normalize( IN.normal * 2 - 1 ); //Decompress
	OUT.normal = normalize( mul(OUT.normal, (float3x3)world) ); //Rotate normals but don't translate them
	OUT.color = IN.color;
	
	//Figure hight of pixel in world coordinates
	OUT.height = worldpos.z;

	return OUT;
}

StatRefVertOut StaticReflectionInstVS( StatInstVertIn IN ) {
	StatRefVertOut OUT;
	
	OUT.texcoords = IN.texcoords;
	
	//Pack instance transform
    float4x4 worldmat = float4x4(IN.m1, IN.m2, IN.m3, IN.m4);

	float4 worldpos = mul(IN.pos, worldmat);
	
	//Define % to 	Fog
	float3 EyeVec = worldpos.xyz - float3(EyePos.xy,2*WaterLevel-EyePos.z);
	float dist = length(EyeVec);
	EyeVec /= dist;
	
	//Define % to Fog
#if EXPFOG == 1
	OUT.fog = saturate( exp(-(max(0,worldpos.z)/(0.0001+saturate(EyeVec.z)))/ExpFogRangeMinusStart) );
#else
	OUT.fog = 	saturate(
					saturate( (FogRange - dist ) / (FogRangeMinusStart) ) /
					(0.001 + saturate( (FogRange - (EyePos.z-WaterLevel)/(0.001+saturate(EyeVec.z)) ) / (FogRangeMinusStart) ))
				);
#endif	
	
	
	//OUT.fog = saturate( (FogRange -  dist) / (FogRangeMinusStart) );
	
	//Projection
	OUT.pos = mul(worldpos, view);
	OUT.pos = mul(OUT.pos, proj);
	
	//Lighting
	OUT.normal = normalize( mul(IN.normal, (float3x3)worldmat) );
	OUT.color = IN.color;
		
	//Figure height of pixel in world coordinates
	OUT.height = worldpos.z;
		
	return OUT;
}

float4 StaticReflectionPS( StatRefVertOut IN ) : COLOR0 {
	//Clip to water plane
	clip(IN.height+4-WaterLevel);
	clip(IN.fog-0.001);
	
	float4 Result = tex2D( s3, IN.texcoords);
	clip(Result.a - 0.5);
	
	//Lighting
	float3 normal = normalize(IN.normal);
	Result.rgb *= saturate( (saturate(dot(-SunVec,normal)) * SunCol * IN.color) + (SunAmb * IN.color) );
	
	//let reflections fade to water color
	Result.rgb = lerp( FogCol2, Result.rgb, IN.fog );
	return float4(Result.rgb,saturate(3.5*IN.fog));
}

struct LandRefVertOut {
	float4 pos: POSITION;
	float2 texcoord: TEXCOORD1;
	float fog: TEXCOORD2;
	float height: TEXCOORD3;
};
LandRefVertOut LandscapeRefVS( float4 pos: POSITION, float2 texcoord: TEXCOORD0 ) {
	LandRefVertOut OUT;
	
	//Lower vertices so there are fewer seams visible in the reflection
	pos.z -= 20 * saturate( 1-(pos.z/100) );
	
	float3 EyeVec = pos.xyz - float3(EyePos.xy,2*WaterLevel-EyePos.z);
	float dist = length(EyeVec);
	EyeVec /= dist;
	
	//Define % to Fog
#if EXPFOG == 1
	OUT.fog = saturate( exp(-(max(0,pos.z)/(0.0001+saturate(EyeVec.z)))/ExpFogRangeMinusStart) );
#else
	OUT.fog = 	saturate(
					saturate( (FogRange - dist ) / (FogRangeMinusStart) ) /
					(0.001 + saturate( (FogRange - (EyePos.z-WaterLevel)/(0.001+saturate(EyeVec.z)) ) / (FogRangeMinusStart) ))
				);
#endif	
	
	//OUT.pos = mul(pos, worldviewproj);
	OUT.pos = mul(pos, world);
	OUT.pos = mul(OUT.pos, view);
	OUT.pos = mul(OUT.pos, proj);	
	OUT.texcoord = texcoord;
	
	//Define height of pixel for clipping to water plane
	OUT.height = pos.z;

	return OUT;
}
float4 LandscapeRefPS( in LandRefVertOut IN ) : COLOR0 {
	//Clip to water plane
	clip(IN.height+4-WaterLevel);
	clip(IN.fog-0.001);
	
	//Normalize incoming normal
	float3 normal = normalize(tex2D(s1,IN.texcoord).rgb * 2 - 1);
	
	//World Texture
	float3 Result = tex2D(s3,IN.texcoord).rgb;
	
	//Detail Texture
	float detail = tex2D(s2,IN.texcoord * 1064).g + 0.5;
	detail *= tex2D(s2,IN.texcoord * 333).g + 0.5;
	detail *= tex2D(s2,IN.texcoord * 90).g + 0.5;
	
	//Lighting
	Result *= detail * saturate( (saturate(dot(-SunVec,normal)) * SunCol) + SunAmb );
	
	//let reflections fade to water color
	Result.rgb = lerp( FogCol2, Result.rgb, IN.fog );
	return float4(Result,saturate(3.5*IN.fog));
}

struct LowestLandVertOut {
	float4 position : POSITION;
	float4 pos : TEXCOORD0;
	float2 texcoords : TEXCOORD1;
	float3 light : COLOR0;
};

LowestLandVertOut LowestLandVS( in float4 pos : POSITION ) {
	LowestLandVertOut OUT;
	
	//float4 modpos = float4(pos.xy, -2080, pos.w);
	
	//OUT.position = mul( modpos, worldviewproj);
	//OUT.position = mul(modpos, world);
	OUT.position = mul(pos, world);
	OUT.position = mul(OUT.position, view);
	OUT.position = mul(OUT.position, proj);
	
	//OUT.pos = float4(modpos.xy - offset, modpos.zw);
	OUT.pos = float4(pos.xy - offset, pos.zw);
	
	//Calculate texture coordinates
	OUT.texcoords = OUT.pos.xy/600;
	
	//Lighting
	float3 normal = float3(0,0,1);
	
	OUT.light = dot(normal,-SunVec) * SunCol;
	
	OUT.light = saturate(OUT.light) + saturate(SunAmb);
	
	return OUT;
}

float4 LowestLandPS( in LowestLandVertOut IN ) : COLOR0 {  
	//Define % to Fog
	float fog = saturate( (FogRange - length(IN.pos.xyz - EyePos.xyz) ) / (FogRangeMinusStart) );
	
	float3 Result = tex2D( s3, IN.texcoords).rgb;
	Result *= IN.light;
	
	//Fogging
	Result = lerp(FogCol2, Result, fog);
	
	return float4(Result, 1);
}

struct WaterVertOut {
	float4 position : POSITION;
	float4 pos : TEXCOORD0;
	float2 texcoord1 : TEXCOORD2;
	float2 texcoord2 : TEXCOORD3;
	float2 texcoord3 : TEXCOORD4;
	float4 screenpos : TEXCOORD5;
	float w : TEXCOORD6;
};

WaterVertOut WaterVS( in float4 pos : POSITION ) {
	WaterVertOut OUT;
	
	//OUT.position = mul( pos, worldviewproj);
	OUT.position = mul(pos, world);
	OUT.position = mul(OUT.position, view);
	OUT.position = mul(OUT.position, proj);
	OUT.w = OUT.position.w;

	OUT.screenpos = mul( pos, TexProj );
	
	OUT.pos = float4(pos.xy - offset, pos.zw);
	
	//Calculate various texture coordinates
	OUT.texcoord1 = OUT.pos.xy/5200;
	OUT.texcoord2 = OUT.pos.xy/1472;
	//OUT.texcoord2 = OUT.pos.xy/2472;
	OUT.texcoord3 = OUT.pos.xy/892;
			
	return OUT;
}

float3 GetFinalWaterNormal( float2 texcoord1, float2 texcoord2, float dist ) : NORMAL {
	//Blend together the normals from different sized areas of the same texture.
	float3 far_normal = tex2D(s5,texcoord1).rgb;
	float3 close_normal = tex2D(s5,texcoord2).rgb;
		                      
	return (lerp( close_normal, far_normal, saturate(dist/8000) )*2-(1).xxx);
}

static const int blursize = 8;
static const float3 blurmap[blursize] = {
  { 1.00,  0.00,  0.100},
  { 0.67,  0.33,  0.115},
  { 0.33, -0.33,  0.135},
  { 0.00,  0.67,  0.150},
  { 0.00, -0.67,  0.150},
  {-0.33,  0.33,  0.135},
  {-0.67, -0.33,  0.115},
  {-1.00,  0.00,  0.100}
};

float4 ReflectionShader2( in WaterVertOut IN ) : COLOR0
{	
    //Calculate eye vector
    float3 EyeVec = (EyePos - IN.pos.xyz);
    float dist = length(EyeVec);
    //float xydist = length(EyeVec.xy);
	EyeVec /= dist;
	
    //Define % to Fog
#if EXPFOG == 1
	float fog = getFog(dist);
#else
    float fog = saturate( ( FogRange - dist ) / (FogRangeMinusStart) );
#endif	
      
    //Sample depth texture
    float depth = max(0, tex2Dproj(s7, IN.screenpos).r - IN.w);
    
    //Calculate water normal
	float3 normal = normalize(float3(GetFinalWaterNormal( IN.texcoord1, IN.texcoord2, dist ).rg,1));
	
    //reflection/refraction strength factor, wind strength increases distortion
	float2 reffactor = ( (dist/30 * (_windfactor)) + 0.2) * (normal.xy);
    
    //Sample refraction texture   
	float4 newscrpos = IN.screenpos + float4(reffactor.yx,0,0);
	depth = max(0, tex2Dproj(s7, newscrpos).r - IN.w);
	newscrpos = IN.screenpos + saturate(depth/100) * float4(reffactor.yx,0,0);
	
    float3 Refract = tex2Dproj(s4, newscrpos).rgb;
	depth = max(0, tex2Dproj(s7, newscrpos).r - IN.w);
	depth /= dot(-EyeVec,float3(view[0][2],view[1][2],view[2][2]));
	
	float depthscale = saturate(exp(-depth/800));
	
#if CAUSTICINT >= 1
    //Add caustic lights
	float3 uwpos = IN.pos - EyeVec*depth;
	float sunraypath = (uwpos.z/SunVec.z);
	float caust = lerp(0.5,tex2D(s5,(uwpos-SunVec*sunraypath).xy/1472).b,
						( (depth/500)*depthscale )*fog*cauststr);	
	Refract *= 0.5+caust;
#endif
	
    //Make transition between actual refraction image and depth color depending on water depth
    Refract = lerp(_depthcolor, Refract, depthscale);
    
    //Sample reflection texture
    float3 Reflect = {0,0,0};
    
    //float totalalpha;
		
    // Refection map is not being updated when Camera height is < 0, replace with solid color
    // looks ugly, but still better than a reflection map that is moving with the view
    if (EyePos.z < WaterLevel)
    {
        Reflect = _depthcolor;
    }
    else
    {
#if WATERBLUR == 1
		//Factor for low view angle
		//float anglefactor = pow(1-EyeVec.z,5);
		
        float4 pixel;     
        //float blurwidth = IN.w * (0.0135 * saturate(pow(dist/65000,2) + dist/250000 + 0.3*anglefactor) + 0.0012); 
		float blurwidth = IN.w * (1-EyeVec.z) * 0.005; 
        float4 scrpos = IN.screenpos - float4(2.5 * reffactor.x,-abs(reffactor.y),0,0) + float4(0,0.0015*IN.w,0,0);
		
        for( int i=0; i<blursize; i++)
        {
          pixel = tex2Dproj( s0, scrpos + blurwidth*float4(blurmap[i].xy,0,0) );
		  Reflect += (pixel.rgb) * blurmap[i].z;
        }
#else
		Reflect = tex2Dproj( s0, IN.screenpos - float4(2.5 * reffactor.x,-abs(reffactor.y),0,0) + float4(0,0.0015*IN.w,0,0) );
#endif
    }
	
	Reflect = lerp(FogCol2, Reflect, fog);
	
	float fresnel = 1-dot(EyeVec,lerp(normal,float3(0,0,1),(1-exp(-dist/3500))*pow(1-EyeVec.z,1.5)))*fog;
	fresnel = pow(saturate(fresnel),5);
	float3 Result = lerp( Refract, Reflect, fresnel );
	
    //Specular lighting
    float reflection = saturate(1.0025*dot(EyeVec,reflect(-SunPos,normalize(normal*float3(1.5,1.5,1)))));
    float3 spec = SunCollf * (pow(reflection,150) + 0.07*pow(reflection,5)) * fog;
    
	//Result = 1500/(1500+tex2Dproj(s7, IN.screenpos).r) ;
	
	//smooth transition at shore line
	Result = lerp(Result+spec, Refract, pow(depthscale,8)*fog );
	
	return float4(Result,1);
}


float4 NonReflectionShader( in WaterVertOut IN ) : COLOR0
{
    //Calculate eye vector
    float3 EyeVec = (EyePos - IN.pos.xyz);
    float dist = length(EyeVec);
	EyeVec /= dist;
	
    //Define % to Fog
    float fog = saturate( ( FogRange - dist ) / (FogRangeMinusStart) );
      
    //Sample depth texture
    float depth = max(0, tex2Dproj(s7, IN.screenpos).r - IN.w);
    
    //Calculate water normal
	float3 normal = normalize(float3(GetFinalWaterNormal( IN.texcoord1, IN.texcoord2, dist ).rg,1));
	
    //reflection/refraction strength factor, wind strength increases distortion
	float2 reffactor = ( (dist/30 * (_windfactor)) + 0.2) * (normal.xy);
    
    //Sample refraction texture   
	float4 newscrpos = IN.screenpos + float4(reffactor.yx,0,0);
	depth = max(0, tex2Dproj(s7, newscrpos).r - IN.w);
	newscrpos = IN.screenpos + saturate(depth/100) * float4(reffactor.yx,0,0);
	
    float3 Refract = tex2Dproj(s4, newscrpos).rgb;
	depth = max(0, tex2Dproj(s7, newscrpos).r - IN.w);
	depth /= dot(-EyeVec,float3(view[0][2],view[1][2],view[2][2]));
	
	float depthscale = exp(-depth/800);
	
#if CAUSTICINT >= 1
    //Add caustic lights
	float3 uwpos = IN.pos - EyeVec*depth;
	float sunraypath = (uwpos.z/SunVec.z);
	float caust = lerp(0.5,tex2D(s5,(uwpos-SunVec*sunraypath).xy/1472).b,
						( (depth/500)*depthscale )*fog*cauststr);	
	Refract *= 0.5+caust;
#endif
	
    //Make transition between actual refraction image and depth color depending on water depth	
    Refract = lerp( _depthcolor, Refract, depthscale);
    
	float fresnel = 1-dot(EyeVec,lerp(normal,float3(0,0,1),(1-exp(-dist/3500))*pow(1-EyeVec.z,1.5)))*fog;
	fresnel = pow(saturate(fresnel),5);
	
	float3 Reflect = (FogCol2+SkyCol)*0.5;
    if(SunVec.z > 0.9)
	{
		Reflect = FogCol2*0.5;
	}
	Reflect = lerp(FogCol2, Reflect, fog);
	
	float3 Result = lerp( Refract, Reflect, fresnel );
	
    //Specular lighting
    float reflection = saturate(1.0025*dot(EyeVec,reflect(-SunPos,normalize(normal*float3(1.5,1.5,1)))));
    float3 spec = SunCollf * (pow(reflection,150) + 0.07*pow(reflection,5)) * fog;
    
	Result = lerp(Result+spec,Refract,pow(depthscale,8)*fog);
	
	return float4(Result,1);
}

float4 UnderWaterPS( in WaterVertOut IN ) : COLOR0
{
    //Define % to Fog
    float dist = length(IN.pos.xyz - EyePos.xyz);
#if EXPFOG == 1
	float fog = getFog(dist);
#else
    float fog = saturate( ( FogRange - dist ) / (FogRangeMinusStart) );
#endif	
    
    //Calculate eye vector
    float3 EyeVec = normalize(EyePos - IN.pos.xyz);
    
    //Factor for low view angle
    float anglefactor = pow(1+EyeVec.z,5);
       
	float3 normal = -normalize(float3(GetFinalWaterNormal( IN.texcoord1, IN.texcoord2, dist ).rg,1));
    
    //fresnel factor
    float fresnel = saturate(1-dot(EyeVec,normal));
	fresnel = pow(fresnel,5);
    
    //refraction strength factor
    float2 refrfactor = normal.xy*(dist/40);
    
    //Sample refraction texture   
    float3 Refract = tex2Dproj(s4, IN.screenpos + float4(refrfactor.yx,0,0)).rgb;
    
    float3 Result= lerp(Refract, FogCol2, fresnel*0.6 );
    Result *= 1+0.22*(dot(normal,-SunVec));
        
    if(SunVec.z < 0.9)
    { // pseudoexterior
        
        //Specular lighting
        float reflection = saturate(1.005*dot(EyeVec,reflect(normalize(float3(-SunPos.x,-SunPos.y,SunPos.z)),normal)));
        float3 Specular = (SunCollf / float3(0.21,0.23,0.29)) * (pow(reflection,150) );
        
        Result += Specular;
    }
    
    //Fogging
    Result = lerp( FogCol2, Result, fog );
        
    return float4( Result , 1);
}

struct LandVertOut {
	float4 pos: POSITION;
	float2 texcoord: TEXCOORD1;
	float3 position: TEXCOORD2;
#if EXPFOG == 1
	float4 fog : TEXCOORD3;
#else
	float fog : TEXCOORD3;
#endif	

};

LandVertOut LandscapeVertexShader( float4 pos: POSITION, float2 texcoord: TEXCOORD0 ) {
	LandVertOut OUT;

#if EXPFOG == 1
	float3 EyeVec = pos.xyz - EyePos.xyz;
	float dist = length(EyeVec);
	EyeVec /= dist;
	
	//Define % to Fog
	OUT.fog = float4(lerp(FogCol2,SkyCol, skyfogblend(EyeVec.z)), getFog(dist) );
#else
    float dist = length(pos.xyz - EyePos.xyz);
	
	//Define % to Fog
	OUT.fog = saturate( (FogRange - dist ) / (FogRangeMinusStart) );
#endif	
	
	//Lower vertices that are close to the camera to ensure they are always below it
	float disp = lerp( 200, 0, saturate(dist/2000));
	pos.z -= disp;
	
	//OUT.pos = mul(pos, worldviewproj);
	OUT.pos = mul(pos, world);
	OUT.pos = mul(OUT.pos, view);
	OUT.pos = mul(OUT.pos, proj);
		
	OUT.texcoord = texcoord;
	OUT.position = pos;
	
	return OUT;
}
float4 LandscapePixelShader( in LandVertOut IN ) : COLOR0 {
	//Normalize incoming normal
	float3 normal = normalize(tex2D(s1,IN.texcoord).rgb * 2 - 1);
	
	//World Texture
	float3 color = tex2D(s3,IN.texcoord).rgb;
	
	//Detail Texture
	float detail = tex2D(s2,IN.texcoord * 1064).g + 0.5;
	detail *= tex2D(s2,IN.texcoord * 333).g + 0.5;
	detail *= tex2D(s2,IN.texcoord * 90).g + 0.5;
		
	//Lighting
	color *= detail * saturate( (saturate(dot(-SunVec,normal)) * SunCol) + SunAmb );
	
	//Define % to Fog
	
#if EXPFOG == 1
	color = lerp(IN.fog.rgb, color, IN.fog.a);
	return float4( color, 1 - IN.fog.a );
#else
	color = lerp(FogCol2, color, IN.fog);
	return float4( color, 1 - IN.fog );
#endif	
}

struct GrassVertIn {
	float4 pos : POSITION;
	float3 normal : NORMAL;
	float4 color : COLOR0;
	float2 texcoords : TEXCOORD0;
};

struct GrassVertOut {
	float4 pos : POSITION;
	float2 texcoords : TEXCOORD0;
	float3 color : COLOR0;
	
#if EXPFOG == 1
	float4 fog : TEXCOORD1;
#else
	float fog : TEXCOORD1;
#endif	

	float4 screenpos: TEXCOORD4;
	float blend : TEXCOORD5;
};

GrassVertOut GrassVS( GrassVertIn IN ) {
	GrassVertOut OUT;
	
	OUT.texcoords = IN.texcoords;
		
	//Animate grass
	float4 worldpos = mul(IN.pos, world);

	float height = clamp(IN.pos.z, 0, 100) / 100;
	
	float2 wind = WindVec * 2.5 + 0.25;
		
	float2 pos_ticks1 = worldpos.xy / 1000 + ticks;
	float2 pos_ticks2 = worldpos.xy / 750 + ticks * 2;
	float2 pos_ticks3 = worldpos.xy / 500 + ticks * 3;
	float2 pos_ticks4 = worldpos.xy / 200 + ticks * 4;
	
	worldpos.xy += ( sin(pos_ticks1) + cos(pos_ticks2) + sin(pos_ticks3) + cos(pos_ticks4) ) * height * wind * 10;
	
	//Define % to Fog
#if EXPFOG == 1
	float3 EyeVec = worldpos.xyz - EyePos.xyz;
	float dist = length(EyeVec);
	EyeVec /= dist;
	OUT.fog = float4(lerp(FogCol2,SkyCol, skyfogblend(EyeVec.z)), getFog(dist) );
#else
	float dist = length(worldpos.xyz - EyePos.xyz);
	OUT.fog = saturate( (FogRange - dist) / (FogRangeMinusStart) );
#endif	

	
	//Define % to Blend
	OUT.blend = saturate( (BlendEnd - dist) / (BlendEnd-BlendStart) );

	//Projection
	OUT.pos = mul(worldpos, view);
	OUT.pos = mul(OUT.pos, proj);
	
	//Texture Projection
	OUT.screenpos = mul( worldpos, TexProj );
	
	//Lighting
	OUT.color = (SunCol * 0.25) + SunAmb;

	return OUT;
}

GrassVertOut GrassInstVS( StatInstVertIn IN ) {
	GrassVertOut OUT;
	
	//Pack instance transform
    float4x4 worldmat = float4x4(IN.m1, IN.m2, IN.m3, IN.m4);

	OUT.texcoords = IN.texcoords;
	
	//Define % to Fog
	float4 worldpos = mul(IN.pos, worldmat);
	
#if EXPFOG == 1
	float3 EyeVec = worldpos.xyz - EyePos.xyz;
	float dist = length(EyeVec);
	EyeVec /= dist;
	OUT.fog = float4(lerp(FogCol2,SkyCol, skyfogblend(EyeVec.z)), getFog(dist) );
#else
	float dist = length(worldpos.xyz - EyePos.xyz);
	OUT.fog = saturate( (FogRange - dist) / (FogRangeMinusStart) );
#endif	
	
	OUT.blend = 1 - (saturate( (GrassDist-dist) / (GrassDist/5) ));
	OUT.blend += 0.4;
	OUT.screenpos = 0;
	
	//Animate grass
	float height = clamp(IN.pos.z, 0, 100) / 100;
	
	float2 wind = WindVec / 6;
	
	float2 pos_ticks1 = worldpos.xy / 1000 + ticks;
	float2 pos_ticks2 = worldpos.xy / 750 + ticks * 2;
	float2 pos_ticks3 = worldpos.xy / 500 + ticks * 3;
	float2 pos_ticks4 = worldpos.xy / 250 + ticks * 4;
	
	worldpos.xy += ( sin(pos_ticks1) + cos(pos_ticks2) + sin(pos_ticks3) + cos(pos_ticks4) ) * height * wind * 10;
	
	//Projection
	OUT.pos = mul(worldpos, view);
	OUT.pos = mul(OUT.pos, proj);
	
	//Lighting
	OUT.color = (SunCol * 0.25) + SunAmb;
	
	return OUT;
}

float4 GrassPS( GrassVertOut IN ) : COLOR0 {
	float4 Result = tex2D( s3, IN.texcoords);
	clip(Result.a - 0.4);
	
	//Lighting	
	Result.rgb *= IN.color;

	//Fogging
#if EXPFOG == 1
	Result.rgb = lerp(IN.fog.rgb, Result.rgb, IN.fog.a);
#else
	Result.rgb = lerp(FogCol2, Result.rgb, IN.fog);
#endif	
	
	
	//Blending
	float3 background = tex2Dproj(s0, IN.screenpos).rgb;
	Result.rgb = lerp( background, Result.rgb, IN.blend);

#if EXPFOG == 1
	return float4(Result.rgb, 1 - IN.fog.a);
#else
	return float4(Result.rgb, 1 - IN.fog);
#endif	
}


struct RenderDepthVertIn {
	float4 pos: POSITION;
	float4 blendWeights: BLENDWEIGHT;
	float2 texcoords: TEXCOORD0;
};

struct RenderDepthVertOut {
	float4 pos: POSITION;
	float4 position: TEXCOORD0;
	//float4 col:  COLOR0;
	float2 texcoords: TEXCOORD1;
};

RenderDepthVertOut RenderDepthVS( in RenderDepthVertIn IN ) {
	RenderDepthVertOut OUT;
	
	//float4 worldpos = mul(IN.pos, MatrixPalette[0]);
		
	//float blendWeightsArray[4] = (float[4])IN.blendWeights;
	
	float4 worldpos = 0.0f;
	
	float4 blend = IN.blendWeights;
	
	if ( FogCol == 3 ) {
		blend[3] = 1 - blend[0] - blend[1] - blend[2];
	} else if ( FogCol == 2 ) {
		blend[2] = 1 - blend[0] - blend[1];
	} else if ( FogCol == 1 ) {
		blend[1] = 1 - blend[0];
	}

	//calculate pos
	if ( FogCol == 0 ) {
		//OUT.col = 0.5;
		worldpos = mul(IN.pos, MatrixPalette[0]);
	} else {
		//OUT.col = blend;
		if ( FogCol >= 1 ) {
			worldpos += mul(IN.pos, MatrixPalette[0]) * blend[0];
			worldpos += mul(IN.pos, MatrixPalette[1]) * blend[1];
		}
		if ( FogCol >= 2 ) {
			worldpos += mul(IN.pos, MatrixPalette[2]) * blend[2];
		}
		if ( FogCol >= 3 ) {
			worldpos += mul(IN.pos, MatrixPalette[3]) * blend[3];
		}
	}
	
	OUT.pos = mul(worldpos, view);
	OUT.pos = mul(OUT.pos, proj);
	
	OUT.position = OUT.pos;
	OUT.texcoords = IN.texcoords;
	
	return OUT;
}

float4 RenderDepthPS( RenderDepthVertOut IN ) : COLOR0 {
	//return IN.col;
	if ( TexBlend > 0.5 ) {
		//Apply alpha testing
		float alpha = tex2D( s1, IN.texcoords).a;
		clip(alpha - 0.5);
	}

	////Define % to Blend	
	//float blend = saturate( (BlendEnd - IN.position.w ) / (BlendEnd-BlendStart) );

	//float3 color = lerp( float3(1,1,1), float3(0,0,0), blend );

	return float4(IN.position.w,1,1,1);
}

struct BlendDepthVertIn {
	float4 pos : POSITION;
	float2 texcoord : TEXCOORD0;
};

struct ScreenVertOut {
	float4 pos: POSITION;
	float2 texcoord : TEXCOORD0;
};

ScreenVertOut ScreenQuadVS( in BlendDepthVertIn IN ) {
	ScreenVertOut OUT;
	
	OUT.pos = mul(IN.pos, world);
	OUT.pos = mul(OUT.pos, view);
	OUT.pos = mul(OUT.pos, proj);
	
	OUT.texcoord = IN.texcoord;
	
	return OUT;
}

float4 BlendDepthPS( ScreenVertOut IN ) : COLOR0 {
	//return float4( tex2D( s0, IN.texcoord ).rgb, 1);

	float3 color = tex2D( s4, IN.texcoord ).rgb;
	float depth = tex2D( s0, IN.texcoord ).r;
	
	//Display depth buffer for testing
	//depth = saturate(depth / FogRange);
	//return float4(depth,depth,depth, 1);
					
	//Define % to Blend	
	float blend = saturate( (BlendEnd - depth ) / (BlendEnd-BlendStart) );
	
	return float4(color, 1 - blend);
}

float4 ClearDepthPS( ScreenVertOut IN ) : COLOR0 {
	return float4(FLT_MAX/2,1,1,1);
}

//float blur_weights[4] = { 0.47442968, 0.23392642, 0.02804153, 0.00081723 };

float blur_weights[7] = { 0.199471, 0.176033, 0.120985, 0.064759, 0.026995, 0.008764, 0.002216 };

float2 TwelveKernel[12];

float4 HorizontalBlurPS( ScreenVertOut IN ) : COLOR0 {
	float4 Original = tex2D(s4, IN.texcoord);	
    float3 Blurred = 0;
    float total_weight = 0;
    
	//Early out to prevent night sky blur -tetchy
	if ( Original.a >= 0.9999 ) {
		return Original;
	}

    for(int i = 0; i < 12; i++)
    {
        float4 Current = tex2D(s4, IN.texcoord + TwelveKernel[i] );
        float weight = saturate(Original.a*Current.a);
        Blurred += Current.rgb * weight;
        total_weight += weight;
    }
    Blurred = (Blurred + Original.rgb) / (total_weight + 1.0);
            
    return float4(Blurred, Original.a);
}

float4 VerticalBlurPS( ScreenVertOut IN ) : COLOR0 {
	float4 orig_color = tex2D( s4, IN.texcoord );
			
	//return float4( orig_color.a, orig_color.a, orig_color.a, orig_color.a );
	
	//Early out to prevent night sky blur -tetchy
	if ( orig_color.a >= 0.9999 ) {
		return orig_color;
	}
	
	float2 offset = float2( 0, PixelHeight );

	float4 color = 0;
	
	color += tex2D( s4, IN.texcoord - offset * 6 ) * blur_weights[6];
	color += tex2D( s4, IN.texcoord - offset * 5 ) * blur_weights[5];
	color += tex2D( s4, IN.texcoord - offset * 4 ) * blur_weights[4];
	color += tex2D( s4, IN.texcoord - offset * 3 ) * blur_weights[3];
	color += tex2D( s4, IN.texcoord - offset * 2 ) * blur_weights[2];
	color += tex2D( s4, IN.texcoord - offset ) * blur_weights[1];
	color += orig_color * blur_weights[0];
	color += tex2D( s4, IN.texcoord + offset ) * blur_weights[1];
	color += tex2D( s4, IN.texcoord + offset * 2 ) * blur_weights[2];
	color += tex2D( s4, IN.texcoord + offset * 3 ) * blur_weights[3];
	color += tex2D( s4, IN.texcoord + offset * 4 ) * blur_weights[4];
	color += tex2D( s4, IN.texcoord + offset * 5 ) * blur_weights[5];
	color += tex2D( s4, IN.texcoord + offset * 6 ) * blur_weights[6];
	
	float blur = saturate( color.a * orig_color.a );
	
// //Don't let the sky get too blurry //test no longer needed - tetchy
// if ( orig_color.a <= 0.0001 ) {
// blur = max( 0.75, blur );
// }
	
	color.rgb = lerp(color.rgb, orig_color.rgb, blur );
		
	return float4( color.rgb, orig_color.a);
}

float4 CopyAndSetAlphaPS( ScreenVertOut IN ) : COLOR0 {
	float3 color = tex2D( s4, IN.texcoord ).rgb;

	return float4(color,1);
}

RenderDepthVertOut GrassDepthVS( GrassVertIn IN ) {
	RenderDepthVertOut OUT;
	
	OUT.texcoords = IN.texcoords;
		
	//Animate grass
	float4 worldpos = mul(IN.pos, world);

	float height = clamp(IN.pos.z, 0, 100) / 100;
	
	float2 wind = WindVec * 2.5 + 0.25;
		
	float2 pos_ticks1 = worldpos.xy / 1000 + ticks;
	float2 pos_ticks2 = worldpos.xy / 750 + ticks * 2;
	float2 pos_ticks3 = worldpos.xy / 500 + ticks * 3;
	float2 pos_ticks4 = worldpos.xy / 200 + ticks * 4;
	
	worldpos.xy += ( sin(pos_ticks1) + cos(pos_ticks2) + sin(pos_ticks3) + cos(pos_ticks4) ) * height * wind * 10;
	
	//Projection
	OUT.pos = mul(worldpos, view);
	OUT.pos = mul(OUT.pos, proj);
	
	OUT.position = OUT.pos;

	return OUT;
}

RenderDepthVertOut GrassDepthInstVS( StatInstVertIn IN ) {
	RenderDepthVertOut OUT;
	
	//Pack instance transform
    float4x4 worldmat = float4x4(IN.m1, IN.m2, IN.m3, IN.m4);

	OUT.texcoords = IN.texcoords;
	
	float4 worldpos = mul(IN.pos, worldmat);
	
	//Animate grass
	float height = clamp(IN.pos.z, 0, 100) / 100;
	
	float2 wind = WindVec / 6;
	
	float2 pos_ticks1 = worldpos.xy / 1000 + ticks;
	float2 pos_ticks2 = worldpos.xy / 750 + ticks * 2;
	float2 pos_ticks3 = worldpos.xy / 500 + ticks * 3;
	float2 pos_ticks4 = worldpos.xy / 250 + ticks * 4;
	
	worldpos.xy += ( sin(pos_ticks1) + cos(pos_ticks2) + sin(pos_ticks3) + cos(pos_ticks4) ) * height * wind * 10;
	
	//Projection
	OUT.pos = mul(worldpos, view);
	OUT.pos = mul(OUT.pos, proj);
	
	OUT.position = OUT.pos;
	
	return OUT;
}

float4 WaterBlendPS( in float2 Tex : TEXCOORD0 ) : COLOR0 {
	float4 color = lerp( tex2D( s5, Tex ), tex2D( s6, Tex ), TexBlend );
	//color.rgb = 0.5f+0.5f*normalize(color.rgb*2.0f-1.0f);
	return color;
}
Technique T0
{
	
	//Used to render the reflected landscape
	Pass A // 0
	{
		AlphaBlendEnable=true;
		SRCBLEND = SRCALPHA;
		DESTBLEND = INVSRCALPHA;
		//ColorWriteEnable=red|green|blue|alpha;
		
		AlphaTestEnable=false;		
		FogEnable=false;
		CullMode=CCW;
		
		ZEnable=true;
		ZWriteEnable=true;
		ZFunc=LessEqual;

		VertexShader = compile vs_2_0 LandscapeRefVS();
		PixelShader = compile ps_2_0 LandscapeRefPS();
	}
	//Used to render the landscape
	Pass B // 1
	{
		ZEnable=true;
		ZWriteEnable=true;
		ZFunc=LessEqual;

		AlphaBlendEnable=false;
		AlphaTestEnable=false;
		CullMode=CW;
		FogEnable=false;

		VertexShader = compile vs_2_0 LandscapeVertexShader();
		PixelShader = compile ps_2_0 LandscapePixelShader();
	}
	//Used to render the water in SM 2.0 mode
	Pass C // 2
	{
		AlphaBlendEnable=false;
		AlphaTestEnable=false;
		CullMode=CW;
		FogEnable=false;
		ZEnable=true;
		ZWriteEnable=true;
		ZFunc=LessEqual;
		
		VertexShader = compile vs_2_0 WaterVS();
		PixelShader = compile ps_2_b ReflectionShader2();
	}
	//Used to render the water in SM 3.0 mode
	Pass D // 3
	{
		AlphaBlendEnable=false;
		AlphaTestEnable=false;
		CullMode=CW;
		FogEnable=false;
		ZEnable=true;
		ZWriteEnable=true;
		ZFunc=LessEqual;

		VertexShader = compile vs_2_0 WaterVS();
		PixelShader = compile ps_2_b ReflectionShader2();
	}
	//Used for rendering distant statics
	Pass E // 4
	{
		AlphaBlendEnable=false;
		AlphaTestEnable=false;
		FogEnable=false;
		CullMode=CW;
		ZEnable=true;
		ZWriteEnable=true;
		ZFunc=LessEqual;
		
		VertexShader = compile vs_2_0 StaticVS();
		PixelShader = compile ps_2_0 StaticPS();
	}
	//Used for rendering the water from underneath
	Pass F // 5
	{
		AlphaBlendEnable=false;
		AlphaTestEnable=false;
		CullMode=CCW;
		FogEnable=false;
		ZEnable=true;
		ZWriteEnable=true;
		ZFunc=LessEqual;

		VertexShader = compile vs_2_0 WaterVS();
		PixelShader = compile ps_2_b UnderWaterPS();
	}
	//Used for rendering water in non-reflective mode
	Pass G // 6
	{
		AlphaBlendEnable=false;
		AlphaTestEnable=false;
		CullMode=CW;
		FogEnable=false;
		ZEnable=true;
		ZWriteEnable=true;
		ZFunc=LessEqual;

		VertexShader = compile vs_2_0 WaterVS();
		PixelShader = compile ps_2_b NonReflectionShader();
	}
	//Used for rendering reflected statics
	Pass H // 7
	{
		AlphaBlendEnable=true;
		SRCBLEND = SRCALPHA;
		DESTBLEND = INVSRCALPHA;
		//ColorWriteEnable=red|green|blue|alpha;
		
		AlphaTestEnable=false;		
		FogEnable=false;
		CullMode=CCW;
		ZEnable=true;
		ZWriteEnable=true;
		ZFunc=LessEqual;
		
		VertexShader = compile vs_2_0 StaticReflectionVS();
		PixelShader = compile ps_2_0 StaticReflectionPS();
	}
	//Used for rendering the lowest possible land out into infinity
	Pass I // 8
	{
		AlphaBlendEnable=false;
		AlphaTestEnable=false;
		CullMode=CW;
		FogEnable=false;
		ZEnable=true;
		ZWriteEnable=false;
		ZFunc=LessEqual;

		VertexShader = compile vs_2_0 LowestLandVS();
		PixelShader = compile ps_2_0 LowestLandPS();
	}
	//Used for rendering distant statics with HW instancing
	Pass J // 9
	{
		AlphaBlendEnable=false;
		AlphaTestEnable=false;
		FogEnable=false;
		CullMode=CW;
		ZEnable=true;
		ZWriteEnable=true;
		ZFunc=LessEqual;
		
		VertexShader = compile vs_3_0 StaticInstVS();
		PixelShader = compile ps_3_0 StaticPS();
	}
	//Used for rendering reflected distant statics with HW instancing
	Pass K // 10
	{
		AlphaBlendEnable=true;
		SRCBLEND = SRCALPHA;
		DESTBLEND = INVSRCALPHA;
		//ColorWriteEnable=red|green|blue|alpha;
		
		AlphaTestEnable=false;		
		FogEnable=false;
		CullMode=CCW;
		ZEnable=true;
		ZWriteEnable=true;
		ZFunc=LessEqual;

		VertexShader = compile vs_2_0 StaticReflectionInstVS();
		PixelShader = compile ps_2_0 StaticReflectionPS();
	}
	//Used for rendering grass
	Pass L // 11
	{
		AlphaBlendEnable=false;
		AlphaTestEnable=false;
		FogEnable=false;
		CullMode=None;
		ZEnable=true;
		ZWriteEnable=true;
		ZFunc=LessEqual;

		VertexShader = compile vs_2_0 GrassVS();
		PixelShader = compile ps_2_0 GrassPS();
	}
	//Used for rendering grass with instancing
	Pass M // 12
	{
		AlphaBlendEnable=false;
		AlphaTestEnable=false;
		FogEnable=false;
		CullMode=None;
		ZEnable=true;
		ZWriteEnable=true;
		ZFunc=LessEqual;

		VertexShader = compile vs_3_0 GrassInstVS();
		PixelShader = compile ps_3_0 GrassPS();
	}
	//Used for rendering the depth texture
	Pass N // 13
	{
		AlphaBlendEnable=false;
		FogEnable=false;
		CullMode=CCW;
		ZEnable=true;
		ZWriteEnable=true;
		ZFunc=LessEqual;

		VertexShader = compile vs_2_0 RenderDepthVS();
		PixelShader = compile ps_2_0 RenderDepthPS();
	}
	//Used for blending what Morrowind draws with what MGE draws
	Pass O // 14
	{
		AlphaBlendEnable=true;
		SRCBLEND = SRCALPHA;
		DESTBLEND = INVSRCALPHA;
		FogEnable=false;
		CullMode=None;
		ZEnable=false;
		ZWriteEnable=false;

		VertexShader = compile vs_2_0 ScreenQuadVS();
		PixelShader = compile ps_2_0 BlendDepthPS();
	}
	//Used for clearing the depth buffer to FLT_MAX
	Pass P // 15
	{
		FogEnable=false;
		CullMode=None;
		ZEnable=false;
		ZWriteEnable=false;

		VertexShader = compile vs_2_0 ScreenQuadVS();
		PixelShader = compile ps_2_0 ClearDepthPS();
	}
	//Used for horizontal blurring
	Pass Q // 16
	{
		AlphaBlendEnable=false;
		AlphaTestEnable=false;
		FogEnable=false;
		CullMode=None;
		ZEnable=false;
		ZWriteEnable=false;

		VertexShader = compile vs_2_0 ScreenQuadVS();
		PixelShader = compile ps_2_0 HorizontalBlurPS();
	}
	//Used for vertical blurring
	Pass R // 17
	{
		AlphaBlendEnable=false;
		AlphaTestEnable=false;
		FogEnable=false;
		CullMode=None;
		ZEnable=false;
		ZWriteEnable=false;

		VertexShader = compile vs_2_0 ScreenQuadVS();
		PixelShader = compile ps_2_0 VerticalBlurPS();
	}
	//Used to copy a texture to the screen while also setting alpha to 0
	Pass S // 18
	{
		AlphaBlendEnable=false;
		AlphaTestEnable=false;
		FogEnable=false;
		CullMode=None;
		ZEnable=false;
		ZWriteEnable=false;

		VertexShader = compile vs_2_0 ScreenQuadVS();
		PixelShader = compile ps_2_0 CopyAndSetAlphaPS();
	}
	//Used for rendering grass depth
	Pass T // 19
	{
		AlphaBlendEnable=false;
		FogEnable=false;
		CullMode=None;
		ZEnable=true;
		ZWriteEnable=true;
		ZFunc=LessEqual;

		VertexShader = compile vs_2_0 GrassDepthVS();
		PixelShader = compile ps_2_0 RenderDepthPS();
	}
	//Used for rendering grass depth with instancing
	Pass U // 20
	{
		AlphaBlendEnable=false;
		FogEnable=false;
		CullMode=None;
		ZEnable=true;
		ZWriteEnable=true;
		ZFunc=LessEqual;

		VertexShader = compile vs_3_0 GrassDepthInstVS();
		PixelShader = compile ps_3_0 RenderDepthPS();
	}
	//Used for blending the current with next water texture
	Pass V // 21
	{
		AlphaBlendEnable=false;
		FogEnable=false;
		CullMode=None;
		ZEnable=false;
		ZWriteEnable=false;
		PixelShader = compile ps_2_0 WaterBlendPS();
	}
	//Used to set up the render state
	Pass Zero // 22
	{
		AlphaBlendEnable=false;
		AlphaTestEnable=false;
		FogEnable=false;
		FogColor=<FogCol>;
		ColorVertex=false;
		Lighting=false;
		ZEnable=true;
		ZWriteEnable=true;
		ZFunc=LessEqual;
		StencilEnable=false;
		ColorWriteEnable=red|green|blue;
		CullMode=CCW;
		ShadeMode=gouraud;
		ColorOp[0]=selectarg1;
		ColorOp[1]=disable;
		AlphaOp[0]=disable;
		AlphaOp[1]=disable;
		ResultArg[0]=current;
		Texture[0]=null;
		Texture[1]=null;
		Texture[2]=null;
		Texture[3]=null;
		Texture[4]=null;
		Texture[5]=null;
		Texture[6]=null;
		Texture[7]=null;
		TexCoordIndex[0]=0;
		TexCoordIndex[1]=1;
		TexCoordIndex[2]=2;
		TexCoordIndex[3]=3;
		TexCoordIndex[4]=4;
		TexCoordIndex[5]=5;
		TexCoordIndex[6]=6;
		TexCoordIndex[7]=7;
		TextureTransformFlags[0]=0;
		TextureTransformFlags[1]=0;
		TextureTransformFlags[2]=0;
		TextureTransformFlags[3]=0;
		TextureTransformFlags[4]=0;
		TextureTransformFlags[5]=0;
		TextureTransformFlags[6]=0;
		TextureTransformFlags[7]=0;
		MagFilter[0]=Linear;
		MinFilter[0]=Linear;
		MipFilter[0]=Linear;
		Clipping=true;
	}
}