//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------

texture		g_sourceTexture;
texture		g_depthTexture;

texture		g_DiffuseMap;
texture		g_HeightMap;
texture		g_NormalMap;

float4x4	g_mWorld;
float4x4	g_mWorldViewProjection;
float3		g_CamPos;

float4x4	g_mSkyRotation;

float3		g_WaterConstants;	// x = refraction amount, y = reflection amount, z = constant colour amount
float3		g_WaterColour;

#define REFRACTION_WOBBLE	1.2
#define REFLECTION_WOBBLE	2.0

#define SKY_BRIGHTNESS		7.0
	
//-----------------------------------------------------------------------------
// Texture samplers
//-----------------------------------------------------------------------------
sampler SourceSampler = 
sampler_state
{
    Texture = <g_sourceTexture>;
    MinFilter = Linear;  
    MagFilter = Linear;

    AddressU = Clamp;
    AddressV = Clamp;
};

sampler DepthSampler = 
sampler_state
{
    Texture = <g_depthTexture>;
    MinFilter = Linear;  
    MagFilter = Linear;

    AddressU = Clamp;
    AddressV = Clamp;
};

sampler HeightMapSampler = 
sampler_state
{
    Texture = <g_HeightMap>;
    MinFilter = Linear;  
    MagFilter = Linear;
};

sampler NormalMapSampler = 
sampler_state
{
    Texture = <g_NormalMap>;
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
};

sampler DiffuseSampler = 
sampler_state
{
    Texture = <g_DiffuseMap>;
    MinFilter = Linear;  
    MagFilter = Linear;

    AddressU = Clamp;
    AddressV = Clamp;
};
   
//--------------------------------------------------------------------------------------
// Vertex shader output structure
//--------------------------------------------------------------------------------------
struct VS_OUTPUT
{
    float4 Position		: POSITION;		// vertex position
    float2 TextureUV	: TEXCOORD0;	// vertex texture coords
    float3 ScreenPos	: TEXCOORD1;	// Screen space position
    float2 TextureUVA	: TEXCOORD2;
    float2 TextureUVB	: TEXCOORD3;
    float2 TextureUVC	: TEXCOORD4;
    float2 TextureUVD	: TEXCOORD5;
    float3 View			: TEXCOORD6;	 
};



VS_OUTPUT WaterVS(	float4 vPos : POSITION, 
					float3 vNormal : NORMAL,
					float3 vTangent : TANGENT0,
					float2 vTexCoord0 : TEXCOORD0 )
{
    VS_OUTPUT Output;

    // Transform the position from object space to homogeneous projection space
    Output.Position = mul(vPos, g_mWorldViewProjection);
    
    Output.ScreenPos.xy = Output.Position.xy;
    Output.ScreenPos.z = Output.Position.w;
    
    // Calculate world position
    float3 vWorldPos = mul(vPos, g_mWorld);  
  
	float3 vWorldNormal = mul(vNormal, (float3x3)g_mWorld); // (model space)
    float3 vWorldTangent = mul(vTangent, (float3x3)g_mWorld); // (model space)
    float3 vWorldBiNorm = cross( vTangent, vNormal ); // (model space)
  
	// Copy texture coordinate through
	Output.TextureUV = vTexCoord0; 

	float fDelta = 0.004;
	
	Output.TextureUVA = Output.TextureUV + float2(fDelta,0); 
	Output.TextureUVB = Output.TextureUV - float2(fDelta,0);
	Output.TextureUVC = Output.TextureUV + float2(0,fDelta);
	Output.TextureUVD = Output.TextureUV - float2(0,fDelta);

	// Calculate view vector
	float3 vView = (g_CamPos - vWorldPos);
		
	// Transform view vector to tangent space
	Output.View = float3( dot( vView, vWorldTangent ), dot( vView, vWorldBiNorm ), dot( vView, vWorldNormal ) );

    return Output;    
}

//-----------------------------------------------------------------------------
// Name: CopyPS 
// Type: Pixel shader                                      
// Desc: 
//-----------------------------------------------------------------------------
float4 CopyPS( float2 OriginalUV : TEXCOORD0 ) : COLOR
{
    // Lookup the color at this new spot
	return tex2D( SourceSampler, OriginalUV );    
}

//-----------------------------------------------------------------------------
// Name: WaterPS 
// Type: Pixel shader                                      
// Desc: 
//-----------------------------------------------------------------------------
float4 WaterPS( VS_OUTPUT In ) : COLOR
{
	float fWaterDist = length( In.View );
	
	// Normalise the view vector
	float3 vView = normalize( In.View );
		
	// Get per-pixel normal
	float3 vNormal = tex2D( NormalMapSampler, In.TextureUV ) * 2 - 1;
	
	// Calculate texture space from screen space
	float4 vSourceTex;
	vSourceTex.xy = In.ScreenPos.xy * 0.5;
	vSourceTex.z = 0;
	vSourceTex.w = In.ScreenPos.z;
	vSourceTex.x += 0.5*In.ScreenPos.z;
	vSourceTex.y = 0.5*In.ScreenPos.z - vSourceTex.y;
	
	//float fDepth = tex2Dproj( DepthSampler, vSourceTex ).r - fWaterDist;
			
	//fDepth = 1.0 - clamp( fDepth/110.0, 0.0, 1.0 );

	// Fresnel approximation
	//float NdotV = dot( vNormal, vView.xyz );
	
	// Reduces aliasing problems with water on horizon
	//float fNormalWobbleFactor = saturate( 1.1-NdotV );
	
	//vNormal = lerp( vNormal, float3(0,0,1), fNormalWobbleFactor );
	
	// Offset refraction texture coordinate using normal
	vSourceTex.x += vNormal.x * REFRACTION_WOBBLE * In.ScreenPos.z * 0.1;
	vSourceTex.y += vNormal.y * REFRACTION_WOBBLE * In.ScreenPos.z * 0.1;
		
	// Lookup refraction colour
	float3 vColour = tex2Dproj( SourceSampler, vSourceTex );// * fDepth; 
			
	// Calculate reflection vector
	//float3 vR = reflect( vView.xzy, vNormal );
	
	//vR.xz = vR.zx;
		
	//vR = mul( vR, g_mSkyRotation );
		
	// Lookup reflection colour
	//float3 vReflection = texCUBE( DiffuseSampler, vR ) * SKY_BRIGHTNESS * 1.0;
	
	//NdotV = pow( NdotV, 0.6 );
	
	//float OneMinusNdotV = (1-NdotV);
		
	//float3 vFinalColour = vColour*NdotV*g_WaterConstants.x + vReflection*OneMinusNdotV*g_WaterConstants.y + g_WaterColour*g_WaterConstants.z;
	float3 vFinalColour = vColour*g_WaterConstants.x + g_WaterColour*g_WaterConstants.z;
		
	return float4(vFinalColour,1);
}


//-----------------------------------------------------------------------------
// Name: 
// Type: Technique                                     
// Desc: 
//-----------------------------------------------------------------------------
technique Copy
{
    pass P0
    {        
        PixelShader = compile ps_2_0 CopyPS();
    }
}

technique RenderWater
{
    pass P0
    {       
		VertexShader = compile vs_1_1 WaterVS(); 
        PixelShader = compile ps_2_0 WaterPS();
    }
}


