
// Shader output, position and diffuse color
struct VS_OUTPUT
{
    float4 pos  : POSITION;
    float4 diff : COLOR0;
    float2 Txcoord0 : TEXCOORD0;
};

// The world view and projection matrices
float4x4 World: WORLD;
float4x4 ViewProj: VIEWPROJECTION;

float4 EyePt;
float4 CamDirReversed;
float OffsetToEye;
bool UseOffsetToEye;

bool OrthographicView;
bool HasEffect;
float NearPlane;
float FarPlane;
float Amount;
bool InRetopoMode;

float4 LightDir0;
float4 LightColor0;
float4 LightDir1;
float4 LightColor1;
float4 LightDir2;
float4 LightColor2;

float4 AmbientColor;
float4 Diffuse;
bool UseDefaultDiffuse;

VS_OUTPUT VertexShaderUV(float4 Pos  : POSITION, float3 Normal : NORMAL0, float2 Txcoord0 : TEXCOORD0)
{
    // Declare our return variable
    VS_OUTPUT Out = (VS_OUTPUT)0;

    // Transform our position
    float3 p = mul(Pos, World);   
    float3 n = normalize(mul(Normal, World));
	n = normalize(n);		
         
    Out.pos = mul(float4( p.xyz, 1.0f ), ViewProj);
    Out.Txcoord0 = Txcoord0;

	if(OrthographicView)
	{
		Out.pos.z -= Amount;
	}
	else
	{
		Out.pos.z -= Amount*Out.pos.z;
    }

    // 1st light
    float diffuse0 = max(dot(n, LightDir0), 0);  
	float4 diffuseColor0 = LightColor0*diffuse0;

    
    // 2nd light  
    float diffuse1 = max(dot(n, LightDir1), 0);
	float4 diffuseColor1 = LightColor1*diffuse1;
       
    // 3ird light  
    float diffuse2 = max(dot(n, LightDir2), 0);
	float4 diffuseColor2 = LightColor2*diffuse2;
       
    //    
    float4 diffuseColorSum = diffuseColor0 + diffuseColor1 + diffuseColor2;
	Out.diff = AmbientColor + Diffuse*diffuseColorSum;	
	Out.diff.a = Diffuse.a;
	
    // Return
    return Out;
}
VS_OUTPUT VertexShaderModel(float4 Pos  : POSITION, float3 Normal : NORMAL0)
{
    // Declare our return variable
    VS_OUTPUT Out = (VS_OUTPUT)0;

    // Transform our position
    float3 p = mul(Pos, World);
    if(UseOffsetToEye)
    {
		float3 dir;
		if(OrthographicView)
		{
			dir = CamDirReversed;
		}
		else
		{
			dir = EyePt - p;
			dir = normalize(dir);
		}
		p += OffsetToEye * dir;
    }
       
    float3 n = normalize(mul(Normal, World));
	n = normalize(n);		
         
    Out.pos = mul(float4( p.xyz, 1.0f ), ViewProj);
    
    float2 Txcoord0;
    Txcoord0.x = 0;
    Txcoord0.y = 0;
    Out.Txcoord0 = Txcoord0;

	if(OrthographicView)
	{
		Out.pos.z -= Amount;
	}
	else
	{
		Out.pos.z -= Amount*Out.pos.z;
    }

    // 1st light
    float diffuse0 = max(dot(n, LightDir0), 0);  
	float4 diffuseColor0 = LightColor0*diffuse0;

    
    // 2nd light  
    float diffuse1 = max(dot(n, LightDir1), 0);
	float4 diffuseColor1 = LightColor1*diffuse1;
       
    // 3ird light  
    float diffuse2 = max(dot(n, LightDir2), 0);
	float4 diffuseColor2 = LightColor2*diffuse2;
       
    //    
    float4 diffuseColorSum = diffuseColor0 + diffuseColor1 + diffuseColor2;
	Out.diff = AmbientColor + Diffuse*diffuseColorSum;	
	Out.diff.a = Diffuse.a;
	
    // Return
    return Out;
}

VS_OUTPUT VertexShaderLine(float4 Pos  : POSITION, float4 clr : COLOR)
{
    // Declare our return variable
    VS_OUTPUT Out = (VS_OUTPUT)0;

    // Transform our position
    float3 p = mul(Pos, World);
    if(UseOffsetToEye)
    {
		float3 dir;
		if(OrthographicView)
		{
			dir = CamDirReversed;
		}
		else
		{
			dir = EyePt - p;
			dir = normalize(dir);
		}
		p += OffsetToEye * dir;
    }
    
    Out.pos = mul(float4( p.xyz, 1.0f ), ViewProj);
	
	//
	if(OrthographicView)
	{
		float f = Out.pos.z;
		float f1 = pow(f, 8);
		//if(InRetopoMode)
			//f1 = 1.0f;
		Out.pos.z -= Amount*max(0.1f, pow(f1, 1.0f/f1));
	}
	else
	{
		float f = 1.0f - (Out.pos.z - NearPlane)/(FarPlane - NearPlane);
		float f1 = pow(f, 8);
		if(InRetopoMode)
			f1 = 1.0f;
		Out.pos.z -= Amount*Out.pos.z*max(0.1f, pow(f1, 1.0f/f1));
    }
    
    if(UseDefaultDiffuse)
		Out.diff = clr;
	else
		Out.diff = Diffuse;
	
    // Return
    return Out;
}
VS_OUTPUT VertexShaderBackFace(float4 Pos  : POSITION)
{
    // Declare our return variable
    VS_OUTPUT Out = (VS_OUTPUT)0;

    // Transform our position
    float3 p = mul(Pos, World);
    
    Out.pos = mul(float4( p.xyz, 1.0f ), ViewProj);
	
	//
    Out.diff = Diffuse;
	
    // Return
    return Out;
}

technique tUV
{
    pass P0
    {    
        // shaders
        VertexShader = compile vs_1_1 VertexShaderUV();
        PixelShader  = NULL;
    }
}
technique t
{
    pass P0
    {    
        // shaders
        VertexShader = compile vs_1_1 VertexShaderModel();
        PixelShader  = NULL;
    }
}
technique t1
{
    pass P0
    {    
        // shaders
        VertexShader = compile vs_1_1 VertexShaderLine();
        PixelShader  = NULL;
    }
}
technique t2
{
    pass P0
    {    
        // shaders
        VertexShader = compile vs_1_1 VertexShaderBackFace();
        PixelShader  = NULL;
    }
}

