//
// Rain vertex shader
// For method 1 (PGR4 rain)
// NOTES:
// - From ShaderX 7, PGR4 rain
// - Notice the reversal of the mul() arguments! (compared to GLSL/HLSL)
// (c) 12-01-2010 RvG
//


// App to vertex
struct a2v
{
  float3 position : POSITION;
  float2 uv       : TEXCOORD0;
};

// Vertex to fragment shader
struct v2p
{
  float4 position       : POSITION;
  float2 uv             : TEXCOORD0;
  //float3 worldPosition  : TEXCOORD1;
  //float4 color          : COLOR0;         // Diffuse texture
  float4 color          : TEXCOORD1;         // Diffuse texture
};

#define PARTICLE_BOX 20.0f

v2p main
(
  // Inputs
  a2v input,
  
  // Constants
  uniform float4x4 modelViewProj,
  uniform float4x4 prevModelViewProj,  	// Previous MVP for blurring/stretching of particles
  uniform float2   size,			  	// Size of particles
  uniform float3   velocity,			// Velocity of particles
  uniform float3   offset,				// Offset of particles
  uniform float3   forward,	  		// Camera forward vector
  uniform float    alpha,       	// Base alpha
  uniform float3   lightColor,    // Sun color
  uniform float3   lightAmbient,  // Sky color
  uniform float3   eyePosW
)
{
	v2p output;
  
	float3 g_vPositionOffset=offset; //{ 0,0,0 };
	float3 g_vViewPosition=eyePosW; //{ 0,0,0 };
	const float3 g_vForward=forward; //{ 0,0,0 };
	const float2 g_vSizeScale=size; //{ 0.1f,0.1f };
	//const float3 g_vLighting={ 1,0,0 };
	const float g_vLighting=0.5;
	//const float3 g_vAlpha={ 1,1,1 };
	
	// Pass texcoords
	output.uv = input.uv;
	
	float3 position = input.position;
  
	// subtract the offset then fmod into (0.0f, PARTICLE_BOX)
	position.xyz -= g_vPositionOffset.xyz;
	position.xyz = fmod(position.xyz, PARTICLE_BOX);
	
	// centre box on origin
	position.xyz -= (PARTICLE_BOX/2);
	// push along view vector so box is positioned more infront of camera
	position.xyz += g_vForward.xyz;

	// calculate colour based on distance from origin
	float subtractColour = length(position.xyz) / PARTICLE_BOX;
	float distanceColourScale = 1.0f - subtractColour * subtractColour;
	
	// get world position
	float4 worldPositionBottom = float4(position.xyz + g_vViewPosition.xyz, 1.0f);
	float4 worldPositionTop = float4(worldPositionBottom.xyz + velocity.xyz* g_vSizeScale.y, 1.0f);
	//float4 worldPositionTop = float4(worldPositionBottom.xyz + max(velocity.xyz,0.2) * g_vSizeScale.y, 1.0f);
		
	// get projected positions of top and bottom of particle, and top of particle in previous frame
	float4 bottom = mul(modelViewProj,worldPositionBottom);
	float4 top = mul(modelViewProj,worldPositionTop);
	float4 topPrev = mul(prevModelViewProj,worldPositionTop);			// Prev!
	
	// get 2d vector in screenspace between top and bottom of particle
	float2 dir = (top.xy/top.w) - (bottom.xy/bottom.w);
	float2 dirPrev = (topPrev.xy/topPrev.w) - (bottom.xy/bottom.w);
	
	// calculate lengths
	float len = length(dir);
	float lenPrev = length(dirPrev);
	
	// scale colour depending on length
	float lenColourScale = saturate(len/lenPrev);
	
	// get 2d vector perpendicular to velocity
	float2 dirPerp = normalize(float2(-dirPrev.y, dirPrev.x));
	
	// get the final colour including the lighting, distance and length scales, and per instance alpha
	//output.color = lightColor * distanceColourScale * lenColourScale * alpha;
	output.color.rgb=(lightColor+lightAmbient)*distanceColourScale*lenColourScale*alpha;
	//output.colour = g_vLighting * distanceColourScale * lenColourScale * alpha;
	//output.colour = g_vLighting * distanceColourScale * lenColourScale * g_vAlpha.x;
	
//output.worldPosition = worldPositionBottom.xyz;

  // Fade at close range
	float vanishDistSquared=2;
	//float fadeDistSquared=4;

	float4 worldPos = worldPositionBottom;
	float3 diff = float3(worldPos - eyePosW);
	float distSq = dot(diff, diff);
	//float alphaFactor = 1.0f - saturate((fadeDistSquared - distSq) / fadeDistSquared);
	if(distSq < vanishDistSquared)
	{
    // Hide particle
		output.position.x = -2.0f;
		output.position.y = -2.0f;
		output.position.z = -2.0f;
		output.position.w = 1.0f;
	} else
  {	
    // choose either the top or bottom projected position using uv.y
    output.position = lerp(topPrev, bottom, output.uv.y);

    // offset the position of each side of the particle using uv.x 
    output.position.xy += (0.5f - output.uv.x) * dirPerp * g_vSizeScale.x;	
	}
  return output;
}
