////////////////////////////// MOVING GRASS
// Vertex program to wave some grass about
// Assumes UV texture coords of v==0 indicates the top of the grass
void grass_vp(float4 position : POSITION,
			  float3 normal   : NORMAL,
			  float2 uv		  : TEXCOORD0,
			  out float4 oPosition : POSITION,
			  out float2 oUv	   : TEXCOORD0,
			  out float4 oColour    : COLOR,

			  uniform float4x4 worldViewProj,
			  //uniform float4 camObjPos,
			  uniform float4 ambient,
			  uniform float4 objSpaceLight,
			  uniform float4 lightColour,
			  uniform float4 offset)
{
	float4 mypos = position;
	//offset = float4(0.5, 0, 0, 0);
	float4 factor = float4(1,1,1,1) - uv.yyyy;
	mypos = mypos + offset * factor;
	oPosition = mul(worldViewProj, mypos);

	oUv = uv;
    // Color    
	// get vertex light direction (support directional and point)
	float3 light = normalize(objSpaceLight.xyz -  (mypos.xyz * objSpaceLight.w));
	// grass is just 2D quads, so if light passes underneath we need to invert the normal
	// abs() will have the same effect
    float diffuseFactor = abs(dot(normal.xyz, light));
	oColour = ambient + diffuseFactor * lightColour;    
    
}

void grass_fp( float4 position : POSITION,
               float2 uv	         : TEXCOORD0,
               float4 colour         : COLOR,  
               
               out float4 oColour    : COLOR,
              
              uniform sampler2D diffuseMap
              )
{	
    float4 texColor = tex2D(diffuseMap, uv.xy);
    oColour = float4(texColor.rgb * colour.rgb, texColor.a); 
    if(oColour.a < 0.58)
      discard; 
}


void grassTex_vp(
        float4 position : POSITION,
			  float4 normal   : NORMAL,
			  float2 uv		  : TEXCOORD0,
              
			  out float4 oPosition : POSITION,
			  out float2 oUv	   : TEXCOORD0,
			  //out float4 oNormal   : NORMAL,

			  uniform float4x4 worldViewProj,
              
			  uniform float4 ambient,
			  uniform float4 objSpaceLight,
			  uniform float4 lightColour,
              
			  uniform float4 offset)
{	    
     // Position
	float4 mypos = position;
	float4 factor = float4(1,1,1,1) - uv.yyyy;
	mypos = mypos + offset * factor;
	oPosition = mul(worldViewProj, mypos);
    // Texture Coord
	oUv.xy = uv.xy;      
}

/// grass_vp ambient
void grassAmbient_vp(
              float4 position : POSITION,
			  float4 normal   : NORMAL,
			  float2 uv		  : TEXCOORD0,
              
			  out float4 oPosition : POSITION,
			  out float2 oUv	   : TEXCOORD0,
			  out float4 oColour    : COLOR,
			  //out float4 oNormal   : NORMAL,

              //uniform float4 camObjPos,
			  uniform float4x4 worldViewProj,              
			  uniform float4 ambient,
			  uniform float4 offset)
{	
     // Position
	float4 mypos = position;
	float4 factor = float4(1,1,1,1) - uv.yyyy;
	mypos = mypos + offset * factor;
  	oPosition = mul(worldViewProj, mypos);
    // Texture Coord
	oUv.xy = uv.xy;      
    /*
    // Normal
    // Make vec from vertex to camera
    float4 EyeVec = camObjPos - mypos;
    // Dot the v to eye and the normal to see if they point
    //  in the same direction or opposite
    float aligned = dot(normal, EyeVec); // -1..1
    // If aligned is negative, we need to flip the normal
    if (aligned < 0)  
        normal = -normal;  
    //oNormal = normal; 
    */
    // Color    
	oColour = ambient; 
}


void grassAmbient_fp( 
               float4 position : POSITION,
               float2 uv	         : TEXCOORD0,
               float4 colour         : COLOR,  
               
               out float4 oColour    : COLOR,
              
              uniform sampler2D diffuseMap
              )
{	
    float4 texColor = tex2D(diffuseMap, uv.xy);
    oColour = float4(colour.rgb, texColor.a); 
}

//////////////////////// GRASS SHADOW CASTER
// Shadow caster vertex program.
void grasscaster_vp(float4 position : POSITION,
			        float2 uv	    : TEXCOORD0,
              
    			  out float4 oPosition  : POSITION,
    			  out float2 oUv	    : TEXCOORD0,
                  out float2 oDepth	    : TEXCOORD1,

    			  uniform float4x4 worldViewProj,
    			  uniform float4 offset,
                  uniform float4 texelOffsets)
{
	float4 mypos = position;
	float4 factor = float4(1,1,1,1) - uv.yyyy;
	mypos = mypos + offset * factor;
	oPosition = mul(worldViewProj, mypos);

	// fix pixel / texel alignment
	oPosition.xy += texelOffsets.zw * oPosition.w;
    
	oDepth.x = oPosition.z;
	oDepth.y = oPosition.w;
  
  	oUv = uv;
    
}


void grasscaster_fp(
                    float4 position : POSITION,
                    float2 uv	        : TEXCOORD0,
                    float2 depth		: TEXCOORD1,
                         
                    out float4 result : COLOR,
              
                    uniform sampler2D diffuseMap
                    )
{	
	float alpha = tex2D(diffuseMap, uv).a;
	if (alpha > 0.001)
    {
       result = float4(1.0f, 1.0f, 1.0f, 0.0f);
    }
    else
    {
        float finalDepth = depth.x / depth.y;
        // just smear across all components 
        // therefore this one needs high individual channel precision
        result = float4(finalDepth.xxx, 1.0f);
    }
}


//////////////////////// GRASS SHADOW RECEIVER
void grassreceiver_vp(
                float4 position : POSITION,
        			  float4 normal   : NORMAL,
        			  float2 uv		  : TEXCOORD0,
              
			  out float4 oPosition    : POSITION,
			  out float4 oShadowUV    : TEXCOORD0,
			  out float3 oUv	      : TEXCOORD1,
			  out float4 oColour      : COLOR,
        	  //out float4 oNormal      : NORMAL,

              uniform float4x4        world,
			  uniform float4x4        worldViewProj,
              uniform float4x4        texViewProj,
              
              uniform float4 camObjPos,
              
			  uniform float4 objSpaceLight,
			  uniform float4 lightColour,
              
			  uniform float4 offset)
{	    
	float4 mypos = position;
	float4 factor = float4(1,1,1,1) - uv.yyyy;
	mypos = mypos + offset * factor;
	oPosition = mul(worldViewProj, mypos);
	oUv.xy = uv.xy;    
    // Transform position to world space
	float4 worldPos = mul(world, mypos);    
	// calculate shadow map coords
	oShadowUV = mul(texViewProj, worldPos);  
       
    // Make vec from vertex to camera
    float4 EyeVec = camObjPos - mypos;
    // Dot the v to eye and the normal to see if they point
    // in the same direction or opposite
    float alignedEye = dot(normal, EyeVec); // -1..1
    // If aligned is negative, we need to flip the normal
    if (alignedEye < 0)  
        normal = -normal;        
    //oNormal = normal;
    
  	// get vertex light direction (support directional and point)
	float3 lightVec = normalize(objSpaceLight.xyz -  (mypos.xyz * objSpaceLight.w));
    // Dot the v to light and the normal to see if they point
    // in the same direction or opposite
    float alignedLight = dot(normal.xyz, lightVec); // -1..1
    // If aligned is negative, shadowing/lighting is not possible.
    oUv.z = (alignedLight < 0)? 0 : 1 ;
         
    float diffuseFactor = max(alignedLight, 0);
	//oColour = diffuseFactor * lightColour;    
	oColour = lightColour;    
}
  	
  	
void grassreceiver_fp( 
                         float4 position : POSITION
                       , float4 shadowUV    : TEXCOORD0
                       , float3 uv	        : TEXCOORD1
                       , float4 vertexLight : COLOR     
                      
                       , out float4 oColour : COLOR
              
                       , uniform sampler2D shadowMap : register(s0)
                       , uniform sampler2D diffuseMap : register(s1)
                      
                      //, uniform float inverseShadowmapSize
                      , uniform float fixedDepthBias
                      , uniform float gradientClamp
                      , uniform float gradientScaleBias
              )
{		
    if (shadowUV.z > 0)
    {
       float4 diffuse = tex2D(diffuseMap, uv.xy);
       if (diffuse.a > 0.001)
       {
            oColour = float4(0.0f, 0.0f, 0.0f, 0.0f);
  }
       else
       {
            // point on shadowmap (no gradient as cg1.4 compiler is unable to handle that complexity)
            shadowUV = shadowUV / shadowUV.w;
            float4 shadowDepths = tex2D(shadowMap, shadowUV.xy);        
            
            float gradientFactor = gradientClamp * gradientScaleBias;
            float depthAdjust = gradientFactor + fixedDepthBias * shadowDepths.x;
            float centerdepth = shadowDepths.x + depthAdjust;
  
            oColour = (centerdepth > shadowUV.z) ? float4(vertexLight.rgb, diffuse.a) : float4(0, 0, 0, diffuse.a);
       }
    }
    else
    {
        oColour = float4(0.0f, 0.0f, 0.0f, 0.0f);
    }
}
