//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
float3 g_LightPos;			        // Light's position in world space
float3 g_LightDir;
float4 g_LightDiffuse;				// Light's diffuse color
float3 g_LightAttenuation;

float3 g_Diffuse;

float3 g_CamPos;					// Camera position
float3 g_CamDir;					// Camera direction

float3 g_time;						// x = time, y = prevTime, z = dt

texture g_NoiseMap;					// Noise texture
texture g_ColourMap;				// Colour gradient texture

float4x4 g_mWorld;                  // World matrix for object
float4x4 g_mWorldViewProjection;    // World * View * Projection matrix
float4x4 g_mWorldViewProjectionPrev;

float4x4 g_mWorldToLightProj;		// Matrix to transform from world space to lights projection space


//--------------------------------------------------------------------------------------
// Texture samplers
//--------------------------------------------------------------------------------------
sampler ColourMapSampler = 
sampler_state
{
    Texture = <g_ColourMap>;
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    AddressU = Clamp;
    AddressV = Clamp;
};



//--------------------------------------------------------------------------------------
// Vertex shader output structure/s
//--------------------------------------------------------------------------------------
struct VS_OUTPUT
{
    float4 Position		: POSITION;		// vertex position 
    float3 Normal		: TEXCOORD0;	// Un-normalised light vector in world space
    float4 PosLight		: TEXCOORD1;	// Fragment position in light's projection space
    float2 LocalPos		: TEXCOORD2;
    float2 TexUV		: TEXCOORD3;
    float2 Depth		: TEXCOORD4;
};

struct WriteVelocityVS_OUTPUT
{
    float4 Position		: POSITION;		// vertex position 
    float2 Velocity		: TEXCOORD0;
};

const float fSize = 0.1;

//--------------------------------------------------------------------------------------
// 
//--------------------------------------------------------------------------------------
VS_OUTPUT RenderSceneVS( float4 vPos : POSITION, 
                         float2 vTexCoord0 : TEXCOORD0, 
                         float3 vTexCoord1 : TEXCOORD1 )
{
    VS_OUTPUT Output;

	float3 vUp = float3(0,1,0);
	float3 vSide = normalize( cross( vUp, g_CamDir ) );
	vUp = normalize( cross( g_CamDir, vSide ) );
	float3 vIn = cross( vUp, vSide );

	float4 vNewPos = vPos;
	
	float fParticleSize = fSize * vTexCoord1.y;

	vNewPos.xyz = vNewPos.xyz + (vSide*(vTexCoord0.x*fParticleSize)) + (vUp*(vTexCoord0.y*fParticleSize));
	
	Output.LocalPos = vTexCoord0;
	
    // Transform the position from object space to homogeneous projection space
	Output.Position = mul(vNewPos, g_mWorldViewProjection);      
   
    // Calculate world position
    float3 vWorldPos = mul(vNewPos, g_mWorld); // position (world space)   
        
	// Copy texture coordinate through
	//Output.TextureUV = vTexCoord1.x; 
				
	// Transform fragment position to lights projection space
	Output.PosLight.xyz = vWorldPos;//mul( vNewPos, g_mWorldToLightProj );
	Output.PosLight.w = 0;
		
	Output.TexUV = vTexCoord1.xy;

	vNewPos.xyz = vPos.xyz + vIn * (fParticleSize * 0.5);
	vNewPos.w = 1;
	
	float4 vFrontPosition = mul(vNewPos, g_mWorldViewProjection);      
   
	Output.Depth.x = Output.Position.z / Output.Position.w;
	Output.Depth.y = Output.Depth.x - vFrontPosition.z / vFrontPosition.w;
	
	Output.Normal = float3(0,0,0);
	
    return Output;    
}

WriteVelocityVS_OUTPUT WriteVelocityVS(	float4 vPos : POSITION, 
										float3 vTexCoord0 : TEXCOORD0, 
										float3 vTexCoord1 : TEXCOORD1 )
{

    WriteVelocityVS_OUTPUT Output;
    
    Output.Position = float4(0,0,0,0); 
    Output.Velocity = float2( 0,0 ); 
     
    return Output;    
}


//--------------------------------------------------------------------------------------
// Pixel shader output structure/s
//--------------------------------------------------------------------------------------
struct PS_OUTPUT_DEPTH
{
    float4	RGBColor : COLOR0;  // Pixel color    
    float	Depth	 : DEPTH;
};

struct PS_OUTPUT
{
    float4	RGBColor : COLOR0;  // Pixel color    
};



//--------------------------------------------------------------------------------------
// 
//--------------------------------------------------------------------------------------
PS_OUTPUT_DEPTH RenderScenePS( VS_OUTPUT In ) 
{ 
    PS_OUTPUT_DEPTH Output;                     	
                     				
	float fCenterDist = (0.2 - length( In.LocalPos )) * 5.0;
	
	// Clip edges
	clip( fCenterDist );
	
	Output.RGBColor.rgb = lerp( float3(0.1,0.1,0.1), float3(2.0,1.8,0.1), In.TexUV.y );
	
	// Get colour from gradient texture
	//Output.RGBColor.rgb = tex2D(ColourMapSampler, In.TexUV) * 1.3;
	
	// Apply noise	
	//Output.RGBColor.g += (tex3D(NoiseMapSampler, In.PosLight.xyz * 5).x - 0.0) * Output.RGBColor.r * 1.0;
	
	Output.RGBColor.rgb *= saturate( (0.2 - length( In.LocalPos ))*5.0 ) * In.TexUV.x;
	
	Output.RGBColor.a = fCenterDist; 
	
	// Set depth (depth replace)
	Output.Depth = In.Depth.x - saturate( (0.2 - length( In.LocalPos ))*5.0 ) * In.Depth.y;
	
    return Output;
}

PS_OUTPUT_DEPTH WriteDepthPS( VS_OUTPUT In ) 
{ 
    PS_OUTPUT_DEPTH Output;
		 	
  	Output.Depth = In.Depth.x - saturate( (0.2 - length( In.LocalPos ))*5.0 ) * In.Depth.y;
  	
  	Output.RGBColor = float4( Output.Depth, 0, 0, 0 );
  			
    return Output;
}


PS_OUTPUT WriteVelocityPS( WriteVelocityVS_OUTPUT In ) 
{ 
    PS_OUTPUT Output;
    
    Output.RGBColor = float4(In.Velocity,1.0f,1.0f);
    
    return Output;
}

    
//--------------------------------------------------------------------------------------
// Renders scene to render target
//--------------------------------------------------------------------------------------
/*
technique AmbientPass_High
{
    pass P0
    {      
		//ZWriteEnable = false;  
		//AlphaBlendEnable = true;   
        VertexShader = compile vs_2_0 RenderSceneVS();
        PixelShader  = compile ps_2_0 RenderScenePS();
    }
}

technique AmbientPass_Medium
{
    pass P0
    {  
		//ZWriteEnable = false; 
		//AlphaBlendEnable = true;   
        VertexShader = compile vs_2_0 RenderSceneVS();
        PixelShader  = compile ps_2_0 RenderScenePS();
    }
}*/

technique RenderScene_High
{
    pass P0
    {      
		//ZWriteEnable = false;  
		//AlphaBlendEnable = true;   
        VertexShader = compile vs_2_0 RenderSceneVS();
        PixelShader  = compile ps_2_0 RenderScenePS();
    }
}

technique RenderScene_Medium
{
    pass P0
    {  
		//ZWriteEnable = false; 
		//AlphaBlendEnable = true;   
        VertexShader = compile vs_2_0 RenderSceneVS();
        PixelShader  = compile ps_2_0 RenderScenePS();
    }
}

technique DepthPass
{
    pass P0
    {      
		ZWriteEnable = true;     
        VertexShader = compile vs_2_0 RenderSceneVS();
    }
}

technique WriteDepthOFF // Using standard depth writing allows rain to not cast shadows
{
    pass P0
    {         
        VertexShader = compile vs_1_1 RenderSceneVS();
        PixelShader  = compile ps_2_0 WriteDepthPS();
    }
}

technique WriteScreenVelocity
{
    pass P0
    {        
        VertexShader = compile vs_1_1 WriteVelocityVS();
        PixelShader  = compile ps_2_0 WriteVelocityPS();
    }
}
