/*********************************************************************NVMH3****

Sky
******************************************************************************/
#include "..\mrt.fx"

//#define FixedPipe

//Experimental Billboarding in VertexShader
float3 ViewPos : ViewPos;
float3 CameraAt : CameraAt;

float4x4 viewProj : ViewProjection;
float4x4 world : World;
float3 campos : CAMERAPOS;

float StartOpacity : StartOpacity;
float EndOpacity : EndOpacity;

float InnerOpacity : InnerOpacity;
float OuterOpacity : OuterOpacity;
float InnerOuterExponent : InnerOuterExponent;

float TaggedBloom : TaggedBloom;

float4 ColorStart : ColorStart;
float4 ColorMid : ColorMid;
float4 ColorEnd : ColorEnd;

float TipFalloffPoint : TipFalloffPoint;
float FinalColorModulate : FinalColorModulate;

float2 UVScale0 : UVScale0;
float2 UVScale1 : UVScale1;

float2 UVTranslate0 : UVTranslate0;
float2 UVTranslate1 : UVTranslate1;

float TextureCutoff : TextureCutoff;

texture MyDiffuseTexture : MyDiffuseTexture;
sampler DiffuseTextureSampler = sampler_state 
{
    texture = <MyDiffuseTexture>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};

struct vertexInput {
    float4 position				: POSITION;
    float4 position2			: POSITION1;
    float2 texCoordDiffuse		: TEXCOORD0;
    float2 texCoordDiffuse2		: TEXCOORD1;
    float2 texCoordDiffuse3		: TEXCOORD2;
};

struct vertexOutput {
    float4 hPosition		: POSITION;
    float2 texCoordDiffuse	: TEXCOORD0;
	float2 texCoordDiffuseLayer2	: TEXCOORD1;
    float2 texCoordDiffuse2	: TEXCOORD2;
    float2 texCoordDiffuse3 : TEXCOORD3;    
    float3 posWorld         : TEXCOORD4;
};

struct vertexOutputFixed {
    float4 hPosition		: POSITION;
    float2 texCoordDiffuse	: TEXCOORD0;
	float4 diffColor		: COLOR0;  
};

vertexOutput VS_Transform(vertexInput IN) 
{
    float4 pos;
    vertexOutput OUT;
///////////////////

#if 1  // billboard in vertex shader
   // Eye vector to beam.
    // E = Cp - B1
    float3 vEye = ViewPos - IN.position;
    
    // Beam vector defined by endpoints.
    // B = B2 - B1
    float3 vBeam = IN.position - IN.position2;

    // Cross product of beam and eye.
    // P = B x E
    float3 vPerpendicularBeam = cross( vBeam, vEye );
    
    // Determine up and right vectors.
    // Bu = (Bf x P) * (1 / ||(Bf x P)||)
    // Br = Bf x Bu
    float3 vUpVector = cross( CameraAt, vPerpendicularBeam );
    vUpVector = normalize(vUpVector);
    
    
    float3 vRightVector = cross( CameraAt, vUpVector );
    
    
    // Form matrix from the vectors.
    
    float4x4 mBillboardMatrix;
    // Right
    mBillboardMatrix[0] = float4( vRightVector, 0 );	  
    // Up
    mBillboardMatrix[1] = float4( vUpVector, 0 );	
    //At
	mBillboardMatrix[2] = float4( CameraAt, 0 );
	// Pos
	mBillboardMatrix[3] = float4( IN.position.xyz, 1 );
	
  
    
    float4 vVertex0h = float4( -IN.texCoordDiffuse3.y, 0, 0, 1 );
    
    vVertex0h = mul( vVertex0h, mBillboardMatrix );
    
    pos = mul(vVertex0h, world);
    
    
    //pos = mul(IN.position, world);
    //pos.y += IN.texCoordDiffuse3.y;
    
	
#else
// old!
	pos = mul(IN.position, world);
	
#endif
    
    OUT.posWorld = pos;
    OUT.hPosition = mul( pos , viewProj);            
     
    OUT.texCoordDiffuse = (IN.texCoordDiffuse + UVTranslate0) * UVScale0;
    OUT.texCoordDiffuseLayer2 = (IN.texCoordDiffuse + UVTranslate1) * UVScale1;
    OUT.texCoordDiffuse2 = IN.texCoordDiffuse2;
    OUT.texCoordDiffuse3 = IN.texCoordDiffuse3;
    
    return OUT;
}


vertexOutputFixed VS_TransformFixed(vertexInput IN) 
{
    float4 pos;
    vertexOutputFixed OUT;
    
       // Eye vector to beam.
    // E = Cp - B1
    float3 vEye = ViewPos - IN.position;
    
    // Beam vector defined by endpoints.
    // B = B2 - B1
    float3 vBeam = IN.position - IN.position2;

    // Cross product of beam and eye.
    // P = B x E
    float3 vPerpendicularBeam = cross( vBeam, vEye );
    
    // Determine up and right vectors.
    // Bu = (Bf x P) * (1 / ||(Bf x P)||)
    // Br = Bf x Bu
    float3 vUpVector = cross( CameraAt, vPerpendicularBeam );
    vUpVector = normalize(vUpVector);
    
    
    float3 vRightVector = cross( CameraAt, vUpVector );
    
    
    // Form matrix from the vectors.
    
    float4x4 mBillboardMatrix;
    // Right
    mBillboardMatrix[0] = float4( vRightVector, 0 );	  
    // Up
    mBillboardMatrix[1] = float4( vUpVector, 0 );	
    //At
	mBillboardMatrix[2] = float4( CameraAt, 0 );
	// Pos
	mBillboardMatrix[3] = float4( IN.position.xyz, 1 );
	
  
    
    float4 vVertex0h = float4( -IN.texCoordDiffuse3.y, 0, 0, 1 );
    
    vVertex0h = mul( vVertex0h, mBillboardMatrix );
    
    pos = mul(vVertex0h, world);

    // old
    //pos = mul(IN.position, world);    
    
    
    OUT.hPosition = mul( pos , viewProj);            
     
    OUT.texCoordDiffuse = (IN.texCoordDiffuse + UVTranslate0) * UVScale0;
    
    float4 colorModulate = float4(1,1,1,1);
    colorModulate.xyz = lerp( ColorStart, ColorMid, min(1, IN.texCoordDiffuse2.x/0.5f) ).xyz;
    colorModulate.xyz = lerp( colorModulate, ColorEnd, max(0, (IN.texCoordDiffuse2.x-0.5f)/(1.0f-0.5f)) ).xyz;
  
    
    float lengthOpacity = lerp( StartOpacity, EndOpacity, IN.texCoordDiffuse2.x );
    float whereWidth = 1.0f - (abs (IN.texCoordDiffuse2.y - 0.5f)) * 2.0f;    
    
    float widthOpacity = lerp( OuterOpacity, InnerOpacity, whereWidth );    
    colorModulate.a = lengthOpacity * widthOpacity;
  
    OUT.diffColor = colorModulate;
    return OUT;
}


//-----------------------------------
PS_OUTPUT PS_Textured( vertexOutput IN)
{    
 
    float4 diffuseTexture = tex2D( DiffuseTextureSampler, IN.texCoordDiffuse);
    float4 diffuseTexture2 = tex2D( DiffuseTextureSampler, IN.texCoordDiffuseLayer2);
 
    diffuseTexture = lerp( diffuseTexture, diffuseTexture2, 0.5f );
    
    float4 colorSum;    
    
    colorSum = diffuseTexture;
    
    float lengthOpacity = lerp( StartOpacity, EndOpacity, IN.texCoordDiffuse2.x );
    float whereWidth = 1.0f - (abs (IN.texCoordDiffuse2.y - 0.5f)) * 2.0f;    
    
    float widthOpacity = lerp( OuterOpacity, InnerOpacity, whereWidth );    
   
    colorSum.a = lengthOpacity * widthOpacity;
   
    float3 colorModulate;
    colorModulate = lerp( ColorStart, ColorMid, min(1, IN.texCoordDiffuse2.x/0.5f) ).xyz;
    colorModulate = lerp( colorModulate, ColorEnd, max(0, (IN.texCoordDiffuse2.x-0.5f)/(1.0f-0.5f)) ).xyz;
  
    colorSum.xyz *= (colorModulate * FinalColorModulate);;
    
    colorSum.w *= IN.texCoordDiffuse3.x * diffuseTexture.w;
    
	PS_OUTPUT Out;
	SetPSOutput( Out, colorSum, float4( campos - IN.posWorld.xyz, TaggedBloom * MRT_FORCE_BLOOM) );
	return Out;
}

//-----------------------------------
PS_OUTPUT PS_TexturedModulate( vertexOutput IN)
{    
 
   	float4 diffuseTexture = tex2D( DiffuseTextureSampler, IN.texCoordDiffuse );
    float4 diffuseTexture2 = tex2D( DiffuseTextureSampler, IN.texCoordDiffuseLayer2 );

	// cutoff actually used as post-modulate modulate 
    diffuseTexture = saturate( diffuseTexture * diffuseTexture2 * TextureCutoff * 2.0f);
    
    float4 colorSum;    
    
    colorSum = diffuseTexture;
    
    float lengthOpacity = lerp( StartOpacity, EndOpacity, IN.texCoordDiffuse2.x );
    float whereWidth = 1.0f - (abs (IN.texCoordDiffuse2.y - 0.5f)) * 2.0f;    
    
    float widthOpacity = lerp( OuterOpacity, InnerOpacity, whereWidth );    
   
    colorSum.a = lengthOpacity * widthOpacity;
   
    float3 colorModulate;
    colorModulate = lerp( ColorStart, ColorMid, min(1, IN.texCoordDiffuse2.x/0.5f) ).xyz;
    colorModulate = lerp( colorModulate, ColorEnd, max(0, (IN.texCoordDiffuse2.x-0.5f)/(1.0f-0.5f)) ).xyz;
  
    colorSum.xyz *= (colorModulate * FinalColorModulate);;
       
	PS_OUTPUT Out;
	SetPSOutput( Out, colorSum, float4( campos - IN.posWorld.xyz, TaggedBloom * MRT_FORCE_BLOOM) );
	return Out;
}


//-----------------------------------
PS_OUTPUT PS_UnTextured( vertexOutput IN)
{    
    
    float4 colorSum;  
    colorSum = float4(1.0f, 1.0f, 1.0f, 1.0f);
    
    float lengthOpacity = lerp( StartOpacity, EndOpacity, IN.texCoordDiffuse2.x );
    float whereWidth = 1.0f - (abs (IN.texCoordDiffuse2.y - 0.5f)) * 2.0f;
    float widthOpacity = lerp( OuterOpacity, InnerOpacity, whereWidth );    
    
    colorSum.a = lengthOpacity * widthOpacity; // * tipOpacity;
    
    float3 colorModulate;
    colorModulate = lerp( ColorStart, ColorMid, min(1, IN.texCoordDiffuse2.x/0.5f) ).xyz;
    colorModulate = lerp( colorModulate, ColorEnd, max(0, (IN.texCoordDiffuse2.x-0.5f)/(1.0f-0.5f)) ).xyz;
  
    colorSum.xyz *= (colorModulate * FinalColorModulate);
    
    
    PS_OUTPUT Out;
	SetPSOutput( Out, colorSum, float4( campos - IN.posWorld.xyz, TaggedBloom * MRT_FORCE_BLOOM) );
	return Out;
}



#ifndef FixedPipe
//-----------------------------------
technique textured
{
    pass p0 
    {	
    	VertexShader = compile vs_2_0 VS_Transform();
		PixelShader  = compile ps_2_0 PS_Textured();
    }
}

//-----------------------------------
technique texturedModulate
{
    pass p0 
    {	
    	VertexShader = compile vs_2_0 VS_Transform();
		PixelShader  = compile ps_2_0 PS_TexturedModulate();
    }
}


//-----------------------------------
technique untextured
{
    pass p0 
    {		
    	VertexShader = compile vs_2_0 VS_Transform();
		PixelShader  = compile ps_2_0 PS_UnTextured();
    }
}

//-----------------------------------
technique texturedNoFog
{
    pass p0 
    {	
        VertexShader = compile vs_2_0 VS_Transform();
		PixelShader  = compile ps_2_0 PS_Textured();
    }
}

//-----------------------------------
technique untexturedNoFog
{
    pass p0 
    {		
        VertexShader = compile vs_2_0 VS_Transform();
		PixelShader  = compile ps_2_0 PS_UnTextured();
    }
}
#else
//-----------------------------------
technique textured
{
    pass p0 
    {	
    	VertexShader = compile vs_2_0 VS_TransformFixed();
		//PixelShader  = compile ps_2_0 PS_Textured();
		PixelShader  = 0;
		
		ColorOp[0] = Modulate; ColorArg1[0] = Texture; ColorArg2[0] = Diffuse;
		AlphaOp[0] = Modulate; AlphaArg1[0] = Texture; AlphaArg2[0] = Diffuse;
		SpecularEnable = false;
		Sampler[0] = <DiffuseTextureSampler>;
		
		ColorOp[1] = Disable;
		AlphaOp[1] = Disable;
    }
}

//-----------------------------------
technique texturedModulate
{
    pass p0 
    {	
    	VertexShader = compile vs_2_0 VS_TransformFixed();
		//PixelShader  = compile ps_2_0 PS_TexturedModulate();
		PixelShader  = 0;
		
		ColorOp[0] = Modulate; ColorArg1[0] = Texture; ColorArg2[0] = Diffuse;
		AlphaOp[0] = Modulate; AlphaArg1[0] = Texture; AlphaArg2[0] = Diffuse;
		SpecularEnable = false;
		Sampler[0] = <DiffuseTextureSampler>;
		
		ColorOp[1] = Disable;
		AlphaOp[1] = Disable;
    }
}


//-----------------------------------
technique untextured
{
    pass p0 
    {		
    	VertexShader = compile vs_2_0 VS_TransformFixed();
		//PixelShader  = compile ps_2_0 PS_UnTextured();
		PixelShader  = 0;
		
		ColorOp[0] = SelectArg1; ColorArg1[0] = Diffuse; 
		AlphaOp[0] = SelectArg1; AlphaArg1[0] = Diffuse;
		SpecularEnable = false;
		
		ColorOp[1] = Disable;
		AlphaOp[1] = Disable;
    }
}

//-----------------------------------
technique texturedNoFog
{
    pass p0 
    {	
     	VertexShader = compile vs_2_0 VS_TransformFixed();
		//PixelShader  = compile ps_2_0 PS_Textured();
		PixelShader  = 0;
		
		ColorOp[0] = Modulate; ColorArg1[0] = Texture; ColorArg2[0] = Diffuse;
		AlphaOp[0] = Modulate; AlphaArg1[0] = Texture; AlphaArg2[0] = Diffuse;
		SpecularEnable = false;
		Sampler[0] = <DiffuseTextureSampler>;
		
		ColorOp[1] = Disable;
		AlphaOp[1] = Disable;
    }
}

//-----------------------------------
technique untexturedNoFog
{
    pass p0 
    {		
     	VertexShader = compile vs_2_0 VS_TransformFixed();
		//PixelShader  = compile ps_2_0 PS_UnTextured();
		PixelShader  = 0;
		
		ColorOp[0] = SelectArg1; ColorArg1[0] = Diffuse; 
		AlphaOp[0] = SelectArg1; AlphaArg1[0] = Diffuse;
		SpecularEnable = false;
		
		ColorOp[1] = Disable;
		AlphaOp[1] = Disable;
    }
}
#endif	