//By EVOLVED
//www.evolved-software.com

//Un-Tweaks
   float4x4 WorldVP:WorldViewProjection; 
   float4x4 World:World;   
   float4x4 ViewInv:ViewInverse; 

//Tweaks
   float FlowTime;
   float4 FlowUV1;
   float4 FlowUV2;
   float3 ReflectColor=float3(1.0,1.0,1.0);
   float3 RefractColor=float3(0.1,0.3,0.5);
   float3 AmbientColor;
   float3 LightDirection;
   float3 LightColor;
   float Heightvec=0.05;

//Textures
   texture NormalMapTexture <string Name = "";>;	
   sampler NormalMapSampler=sampler_state 
      {
 	texture = <NormalMapTexture >;
	MinFilter=Point;
	MipFilter=None;
      };
   texture ReflectionTexture <string Name = "";>;
   sampler ReflectionSampler=sampler_state
      {
 	Texture=<ReflectionTexture>;
      };
   texture FlowMapTexture <string Name = "";>;
   sampler FlowMapSampler=sampler_state
      {
 	Texture=<FlowMapTexture>;
  	MagFilter=anisotropic;
	MinFilter=anisotropic;
	MipFilter=anisotropic;
	MaxAnisotropy=8;
      };

//Structs 
   struct Input
      {
 	float4 Pos:POSITION; 
 	float2 UV:TEXCOORD; 
	float3 Normal:NORMAL;
 	float3 Tangent:TANGENT; 
      };
   struct Output
      {
	float4 Pos:POSITION; 
 	float4 Tex:TEXCOORD0;
 	float2 FlowTex:TEXCOORD1;
  	float3 TBNRow1:TEXCOORD2; 
  	float3 TBNRow2:TEXCOORD3; 
  	float3 TBNRow3:TEXCOORD4;
 	float3 WorldPos:TEXCOORD5;
 	float3 ViewVec:TEXCOORD6;
 	float3 ViewNor:TEXCOORD7;
 	float3 FlowVec:COLOR0;
      };

//Vertex Shader
   Output VS(Input IN)  
      {
 	Output OUT;
  	OUT.Pos=mul(IN.Pos,WorldVP);
	OUT.Tex.xy=(IN.UV*FlowUV1.zw)+FlowUV1.xy;
	OUT.Tex.zw=(IN.UV*FlowUV2.zw)+FlowUV2.xy;
	OUT.FlowTex=IN.UV;
	float3 Normals=normalize(mul(IN.Normal,World)); 
	float3 Tangent=normalize(mul(IN.Tangent,World));
	OUT.TBNRow1=Tangent;
	OUT.TBNRow2=cross(Normals,Tangent);
	OUT.TBNRow3=Normals;
	OUT.WorldPos=mul(IN.Pos,World);
	OUT.ViewVec=ViewInv[3].xyz-OUT.WorldPos;
	float3x3 WorldTBN=float3x3(OUT.TBNRow1,OUT.TBNRow2,OUT.TBNRow3);
	OUT.ViewNor=mul(OUT.ViewVec,transpose(WorldTBN));
	OUT.FlowVec.xy=frac(float2(FlowTime,0.5+FlowTime));
	OUT.FlowVec.z=abs(frac(FlowTime)*2.0-1.0)*2.0-1.0;
	OUT.FlowVec.z=0.5+(pow(abs(OUT.FlowVec.z),1.25)*sign(OUT.FlowVec.z))*0.5;
	return OUT;
      }

//Pixel Shader
   float4 PS(Output IN)  : COLOR
      {
	float2 FlowDir=tex2D(FlowMapSampler,IN.FlowTex).xy*2.0-1.0;
 	float FlowIntensity=pow(dot(FlowDir,FlowDir),0.1);
        IN.Tex +=FlowDir.xyxy*IN.FlowVec.xxyy;
	float3 ViewNor=normalize(IN.ViewNor);
	IN.Tex +=(FlowIntensity*Heightvec*(lerp(tex2D(NormalMapSampler,IN.Tex.xy).w,tex2D(NormalMapSampler,IN.Tex.zw).w,IN.FlowVec.z)-0.5))*ViewNor.xyxy;
	IN.Tex +=(FlowIntensity*Heightvec*(lerp(tex2D(NormalMapSampler,IN.Tex.xy).w,tex2D(NormalMapSampler,IN.Tex.zw).w,IN.FlowVec.z)-0.5))*ViewNor.xyxy;
	IN.Tex +=(FlowIntensity*Heightvec*(lerp(tex2D(NormalMapSampler,IN.Tex.xy).w,tex2D(NormalMapSampler,IN.Tex.zw).w,IN.FlowVec.z)-0.5))*ViewNor.xyxy;
	float4 NormalMap=lerp(tex2D(NormalMapSampler,IN.Tex.xy),tex2D(NormalMapSampler,IN.Tex.zw),IN.FlowVec.z); 
	NormalMap.z +=(1.0-FlowIntensity)*16.0;
 	NormalMap.z +=abs(IN.FlowVec.z*2.0-1.0);
        NormalMap.xyz=normalize(float3(NormalMap.xy*2.0-1.0,NormalMap.z));
	float3x3 WorldTBN=float3x3(IN.TBNRow1,IN.TBNRow2,IN.TBNRow3);
	float3 Normals=mul(NormalMap.xyz,WorldTBN);
	float3 ViewVec=normalize(IN.ViewVec);
	float ViewNormal=max(dot(ViewVec,Normals),0.0);
	float FresnelVec=0.04+0.96*pow(1.0-ViewNormal,2.0);
	float3 HalfVec=normalize(-LightDirection+ViewVec);
	float Light=max(dot(-LightDirection,Normals),0.0);
	float Specular=pow(max(dot(HalfVec,Normals),0.0),64.0)*Light*2.0;
	float3 ViewReflection=reflect(-ViewVec,Normals); 
	float3 Reflection=pow(texCUBE(ReflectionSampler,ViewReflection),2.2);
	float3 ViewRefraction=refract(-ViewVec,Normals,0.01); 
	float3 Refraction=pow(texCUBE(ReflectionSampler,ViewRefraction),2.2);
	float3 Water=lerp(Refraction*RefractColor,Reflection*ReflectColor,FresnelVec);
	return float4(pow(Water*(AmbientColor+LightColor*(Light+Specular)),0.454545),1.0);
      }

//Techniques 
   technique FlowMap
      {
 	pass p0
      {		
 	vertexShader = compile vs_3_0 VS(); 
 	pixelShader  = compile ps_3_0 PS(); 
      }
      }