//Particle shader

#include "atmosphere.cg"
#include "lighting.cg"

// App to vertex
struct a2v
{
  float3 position  : POSITION;
  float4 color     : COLOR;      //optional
  float2 texcoords : TEXCOORD0;
  float2 size      : TEXCOORD1;
};

// Vertex to fragment shader
struct v2p
{
  float4 position       : POSITION;
  float2 uv		        : TEXCOORD0;
  float4 color          : COLOR;         // Diffuse texture
  
  float3 Direction		: TEXCOORD1;
  float4 RayleighColor  : TEXCOORD2;
  float4 MieColor       : TEXCOORD3;
  float3 fPosition      : TEXCOORD4;
  float  extinction     : TEXCOORD6;
};

v2p main
(
  // IN
  a2v IN,
  
  // Constants
  uniform float4x4 modelView,
  uniform float4x4 modelViewProj,
  uniform float3   eyePosW,
  
  uniform float3   lightDirection,
  uniform float3	lightColor,
  //uniform float    time
 
   // Atmosphere
  uniform float    sunIntensity,
  uniform float    atmosRayleigh,
  uniform float    atmosMie,
  uniform float    extinctionFactor
)
{
	v2p OUT;
  OUT.fPosition=IN.position;
	
	float vanishDistSquared=3;
	float fadeDistSquared=4;
	
	float4 worldPos = float4(IN.position, 1);
	float3 diff = float3(worldPos - eyePosW);
	float distSq = dot(diff, diff);
	if(distSq < vanishDistSquared)
	{
    // Hide particle
    OUT.position.x = -2.0f;
    OUT.position.y = -2.0f;
    OUT.position.z = -2.0f;
    OUT.position.w = 1.0f;
		
    // dummy
    OUT.color = IN.color;
    OUT.color.a=0;
    OUT.uv = IN.texcoords;
    OUT.extinction=0;
	}	else
	{
    // Fade amount
    float alphaFactor = 1.0f - saturate((fadeDistSquared - distSq) / fadeDistSquared);
	
    // for every quad particle we get 4x the same IN.position.
    // we use texcoords to offset the position
    float4 outpos = float4(IN.position, 1);
    // Method 2: more performant collective billboarding
    // Get a right and up vector to billboard
    float3 vRight =	modelView._m00_m01_m02;
    float3 vUp 	  = modelView._m10_m11_m12;
    // Create offsets from particle position; only to be scaled by the size
    // outpos.xyz += vRight*sign + vUp*sign
    float3 vertexOffset = vRight * ((IN.texcoords.x*2)-1)*IN.size.x + vUp * ((IN.texcoords.y*2)-1)*IN.size.y;
    outpos.xyz += vertexOffset;
    OUT.fPosition=outpos;
    OUT.position = mul(modelViewProj, outpos);
	
    // Atmosphere
    CalculateAtmosphere(atmosRayleigh,atmosMie,sunIntensity,eyePosW,IN.position,lightDirection,
      OUT.RayleighColor,OUT.MieColor,OUT.Direction);
	
	  // Extinction factor of regular color
    OUT.extinction=CalculateAtmosphereExtinction(OUT.position.xyz,atmosRayleigh,atmosMie,extinctionFactor);
	
    OUT.uv = IN.texcoords;
    OUT.color=IN.color;
    OUT.color.a=IN.color.a*alphaFactor;
  }
    
  return OUT;
}


//
// deprecated
//
	//offset the position based on tex coords
	//float2 size = float2(1,1);
	//outpos.xy += (IN.texcoords*size) - float2(size.x/2, -size.y/2);
	
	//Method 1: individual billboarding
	//now we need to turn the quad to face the camera.
	//float3 vLookat = eyePosW - outpos.xyz;
	//vLookat = normalize(vLookat);
	//float3 vRight = cross( float3(0,0,0), vLookat );  //modelViewProj.
	//float3 vUp = cross(vRight, vLookat);
	//vRight = normalize(vRight);
	//vUp = normalize(vUp);
	
	//if(IN.texcoords.x == 0 && IN.texcoords.y == 0) 	  outpos.xyz += (-vRight - vUp); //00
	//else if(IN.texcoords.x == 0 && IN.texcoords.y == 1) outpos.xyz += (vRight - vUp);  //01
	//else if(IN.texcoords.x == 1 && IN.texcoords.y == 1) outpos.xyz += (vRight + vUp);  //11
	//else if(IN.texcoords.x == 1 && IN.texcoords.y == 0) outpos.xyz += (-vRight + vUp); //10