#ifdef SHADOWS
#include "ShadowMapDx10.fxh"
#ifdef SOFT_SHADOWS
float2 gExpFactor = { 20.000000, 5.000000 }; 
float threshold = 0.000000;
float VarianceShadow( float4 Plc) 
{ 
     float3 Pndc = Plc.xyz / Plc.w; 
    if (any(Pndc < -1.0f) || any(Pndc > 1.0f)) return 1.0f; 
    float2 uv = Pndc.xy * float2(0.5f, -0.5f) + float2(0.5f, 0.5f); 
    float texelSz = gTexelSize; 
    float4 moments = gShadowMapTex.Sample(gShadowMapSamp, uv); 
    float depth = exp(gExpFactor.x * Pndc.z); 
    float p = (depth <= moments.x); 
    float variance = moments.y - moments.x * moments.x; 
    variance = max(variance, 1.0e-3f*max(1.0f, depth*depth)); 
    float d = depth - moments.x; 
    float p_max = variance / (variance + d * d); 
    float posValue = max(p, p_max); 
    depth = -exp(-gExpFactor.y * Pndc.z); 
    p = (depth <= moments.z); 
    variance = moments.w - moments.z * moments.z; 
    variance = max(variance, 1.0e-3f*max(1.0f, depth*depth)); 
    d = depth - moments.z; 
    p_max = variance / (variance + d * d); 
    float negValue = max(p, p_max); 
    float light = min(negValue, posValue);
    return saturate((light-threshold) / (1.0f - threshold));
} 
#endif 
#endif

#define epsilon (10e-6)
#define E 2.71828
#define MAXLIGHTINGNUM 8

#define FOGMODE_LINEAR		0
#define FOGMODE_EXP		1
#define FOGMODE_EXP2		2


struct TripleColor
{
	float4 Ambient;
	float4 Diffuse;
	float4 Specular;
};
struct VSOutput
{
	float4 Pos			: SV_Position;
#ifdef BUMP_TEXTURE
	// Diffuse tex coordinates and bump tex coordinates would be calculated at PS
	float4 Tex				: TEXCOORD0;
#else
	#ifdef DIFFUSE_TEXTURE
		float4 Tex				: TEXCOORD0;
	#endif
#endif //bump mapping

#ifndef IBL
	#ifdef ENVIRONMENT_TEXTURE
		float4 EnvTex		: TEXCOORD1;
	#endif
#endif


	float4 ColorD		: COLOR0;
	float4 ColorS		: COLOR1;


#ifdef BUMP_TEXTURE
	float3 Tangent		: COLOR2;
	float3 Binormal		: COLOR3;
	float3 Locpos		: COLOR4;
#endif

#ifdef IBL
	//Normal and viewer direction at world space
	#ifndef BUMP_TEXTURE
		float3 Normal		: COLOR5;
	#endif
	float3 Viewer		: COLOR6;
#endif

	float  FogFactor	: FOG;
	float4 ClipplaneDist0 	: SV_ClipDistance0;    //clip distance for 4 planes
	float4 ClipplaneDist1 	: SV_ClipDistance1;    //clip distance for 4 planes
	#ifdef SHADOWS
		float4 ShadowPos    	: TEXCOORD2;
		float4 ShadowD      	: TEXCOORD3;
		float4 ShadowS      	: TEXCOORD4;
	#endif
};

#ifdef BUMP_TEXTURE
float		gBumpAmount				: BumpAmount=1.0f;
//Diffuse texture
Texture2D gBumpTex				: BumpTexture =NULL;
cbuffer cbBumpTextures
{
	float4x4 g_matBumpTex			: BumpTexCoordTransMatrix=	
	{
		{1.0f, 0.0f, 0.0f, 0.0f},
		{0.0f, 1.0f, 0.0f, 0.0f},
		{0.0f, 0.0f, 1.0f, 0.0f},
		{0.0f, 0.0f, 0.0f, 1.0f}
	} ; 
};
	
//sampler for various textures
SamplerState gBumpSamp:BumpSampler ;
#endif

#ifdef LIGHTING
struct Light
{
	float4 DiffColor;
	float4 AmbColor;
	float4 SpecColor;
	float3 Dir;
   	float3 Pos;
   	float4 Attenuation;	//1, D, D^2, Range;
   	float4 Spot;		//cos(theta/2), cos(phi/2), falloff
};
#endif


cbuffer cbPerObject
{
	//Material
	float4 g_Emissive			: EmissiveColor;
	float4 g_Ambient			: AmbientColor;
	float4 g_Diffuse			: DiffuseColor;
	float4 g_Specular			: SpecularColor;
	float4 g_Misc				: Miscellaneous = float4(1.0f, 1.0f, 0.0f, 0.0f);//SpecularPower, Opacity, ReflectionBlend, AlphaTestRef
	//Transform
	float4x4 g_matWorldViewProj		: WorldViewProjection;
	float4x4 g_matWorld			: World;
	float4x4 g_matWorldView			: WorldView;
#ifndef	NONORMAL
	float4x4 g_matWorldViewIT		: WorldViewInverseTranspose;
#endif
	bool g_bClippingEnable			:ClippingPlaneFlag = false;
	int g_numClipplane			:clippingplanecount = 0;
	float4 g_clipplanes[8]			:clippingplanes;
};

cbuffer cbPerFrame
{
#ifdef LIGHTING
	//Lights
	Light g_lights[8]			: LightArray;
	int g_numDirLight			: DirLightCount = 0;
	int g_numPointLight			: PointLightCount = 0;
	int g_numSpotLight			: SpotLightCount = 0;
	bool g_enabledLight			:LightEnable=true;
#endif

	//Fog
	bool		g_fogEnabled	: FogEnabled = false;
	int g_fogMode				: FogMode  = FOGMODE_LINEAR;
	float4 g_fogRange			: FogRange = float4(0.0f, 0.0f, 1.0f, 1.0f);//x for start, y for end, z for density
	float4 g_fogColor			: FogColor = float4(0, 0, 0, 0);
	//view transform perframe
	float4x4 g_matViewIT			: ViewInverseTranspose;
	float4x4 g_matView			: View;
	float2		g_ViewPort			: viewportpixelsize;
};

void CalcClipping(float4 LocalPos, inout VSOutput Out)
{
	//fixed function clipping is done in world space
	float4 WorldPos = mul(LocalPos,g_matWorld);
	WorldPos /= WorldPos.w;
	float dist[8] = {1,1,1,1,1,1,1,1};
	for(int i=0;i<g_numClipplane;i++)
	{
		dist[i] = dot( WorldPos, g_clipplanes[i]);
	}
	//calc the distance from the 8 clipping planes
	Out.ClipplaneDist0.x = dist[0];
	Out.ClipplaneDist0.y = dist[1];
	Out.ClipplaneDist0.z = dist[2];
	Out.ClipplaneDist0.w = dist[3];
	Out.ClipplaneDist1.x = dist[4];
	Out.ClipplaneDist1.y = dist[5];
	Out.ClipplaneDist1.z = dist[6];
	Out.ClipplaneDist1.w = dist[7];
}

// Vertex lighting calculation
// A vertex's color is the sum of the contribution from:
// 1. a material emission term, Em
// 2. global ambient lighting, Ag, and a material ambient term, Am
// 3. individual light's contributions L(i)

// VertexColor = Em + Ag*Am + sum(L(i)), where
// L(i) = Attenuation(i)*SpotlightFactor(i)*[Ai*Am + max(L.N, 0)*D(i)*Dm + pow(max(H.N, 0), shineness)*S(i)*Sm]

//-----------------------------------------------------------------------------
// Name: DoDirLight()
// Desc: Directional light computation (in eye space)
// N: Normal in eye space; V: Viewer in eye space; Index: Light Index
//-----------------------------------------------------------------------------

#ifdef LIGHTING
#ifdef NONORMAL
#ifdef ALLLIGHTTYPES
TripleColor DoSpotLightAmb(float4 P,int Index)
{
	TripleColor Out;
	//Ambient
	Out.Ambient = g_lights[Index].AmbColor;
	//Diffuse
	Out.Diffuse = 0;
	//Specular    
	Out.Specular = 0;
    
	float AttenSpot = 1.f;
	float LD = length(g_lights[Index].Pos-(float3)mul(P, g_matWorld));
	if(LD > g_lights[Index].Attenuation.w)
	{
		AttenSpot = 0.f;
	}
	else
	{
		AttenSpot *= 1.f/(g_lights[Index].Attenuation.x + g_lights[Index].Attenuation.y*LD + 
			g_lights[Index].Attenuation.z*LD*LD);
	}
	
	//spot cone computation
	float3 L = mul(normalize((g_lights[Index].Pos-(float3)mul(P, g_matWorld))), 
		(float3x3)g_matViewIT);
	float3 L2 = mul(g_lights[Index].Dir, (float3x3)g_matViewIT);
	float Rho = dot(L, L2);
	AttenSpot *= pow(saturate((Rho - g_lights[Index].Spot.y)/(g_lights[Index].Spot.x - g_lights[Index].Spot.y)), 1.0f);
		//g_lights[Index].Spot.z);
	Out.Ambient *= AttenSpot;
	Out.Diffuse *= AttenSpot;
	Out.Specular *= AttenSpot;
	return Out;
}
TripleColor DoPointLightAmb(float4 P, int Index)
{
	TripleColor Out;
	//Ambient
	Out.Ambient = g_lights[Index].AmbColor;
	//Diffuse
	Out.Diffuse = 0;
	//Specular
	Out.Specular = 0;
  
	//Attenuation
	float Atten = 1.f;
	float LD = length(g_lights[Index].Pos-(float3)mul(P, g_matWorld));
	if(LD > g_lights[Index].Attenuation.w)//Attenuation.w is Range
	{
		Atten = 0.f;
	}
	else
	{
		Atten *= 1.f/(g_lights[Index].Attenuation.x + 
			g_lights[Index].Attenuation.y*LD + 
			g_lights[Index].Attenuation.z*LD*LD);
	}
	Out.Ambient *= Atten;
	return Out;
}
#endif 

//For those case without normal, ambient color is just needed
TripleColor DoDirLightAmb(int Index)
{
   	TripleColor Out;
   	//Ambient
   	Out.Ambient = g_lights[Index].AmbColor;
   	//Diffuse
   	Out.Diffuse = 0;
   	//Specular
   	Out.Specular = 0;
   	return Out;
}

//For those cases without normal
TripleColor CalcLightingAmb(float3 Pos, float4 Emissive,float4 Ambient,float Opacity)
{
	TripleColor Color;
	//Emissive and Ambient lights
	Color.Diffuse = Emissive;

	Color.Specular = 0;
	//directional lights
	[loop] for(int i = 0; i < g_numDirLight; i++)
	{
//		if(i>=g_numDirLight) break;
	
		TripleColor ColOut = DoDirLightAmb(i);
		Color.Diffuse += ColOut.Ambient*Ambient;

	}
	
#ifdef ALLLIGHTTYPES
	float4 LocalPos = float4(Pos,1.0f);
	int Stride = g_numDirLight;
	//point lights
	[loop] for(int j = 0; j < g_numPointLight; j++)
	{
//		if(j>=g_numPointLight) break;

		TripleColor ColOut = DoPointLightAmb(LocalPos,j+Stride);
		Color.Diffuse += ColOut.Ambient*Ambient ;

	}
	Stride = g_numDirLight+g_numPointLight;
	//spot lights
	[loop] for(int k = 0; k < g_numSpotLight; k++)
	{
//		if(k>=g_numSpotLight) break;

		TripleColor ColOut = DoSpotLightAmb(LocalPos,k+Stride);
		Color.Diffuse += ColOut.Ambient*Ambient ;

	}
#endif 

	Color.Diffuse.w = Opacity;//Opacity
	Color.Specular.w = 0;
	return Color;
}

#else

TripleColor DoDirLight(float3 N, float3 V, int Index, float Glossness)
{
   	TripleColor Out;
   	float3 L = mul(g_lights[Index].Dir, (float3x3)g_matViewIT);
   	float NdotL = dot(N, L);
   	//Ambient
   	Out.Ambient = g_lights[Index].AmbColor;
   	//Diffuse
   	Out.Diffuse = max(NdotL, 0.0f) * g_lights[Index].DiffColor;
   	//Specular
   	float3 H = normalize(L + V);   //half vector
   	Out.Specular = 0;
   	if(NdotL>=0.0f)
   	{
      		Out.Specular += pow(max(0, dot(H, N)), Glossness) * g_lights[Index].SpecColor;
   	} 
   	return Out;
}

#ifdef ALLLIGHTTYPES
//-----------------------------------------------------------------------------
// Name: DoPointLight()
// Desc: Point light computation (in eye space)
// P: Position in local space; N: Normal in eye space; V: Viewer in eye space; Index: Light Index
//-----------------------------------------------------------------------------
TripleColor DoPointLight(float4 P, float3 N, float3 V, int Index, float Glossness)
{
	float3 L = mul(normalize((g_lights[Index].Pos-(float3)mul(P, g_matWorld))), (float3x3)g_matViewIT);
	TripleColor Out;
	float NdotL = dot(N, L);
	//Ambient
	Out.Ambient = g_lights[Index].AmbColor;
	//Diffuse
	Out.Diffuse = max(NdotL, 0.0f) * g_lights[Index].DiffColor;
	//Specular
	float3 H = normalize(L + V);   //half vector
	Out.Specular = 0;
    	if(NdotL>=0.0f)
    	{
		Out.Specular += pow(max(0, dot(H, N)), Glossness) * g_lights[Index].SpecColor;
	}
	//Attenuation
	float Atten = 1.f;
	float LD = length(g_lights[Index].Pos-(float3)mul(P, g_matWorld));
	if(LD > g_lights[Index].Attenuation.w)//Attenuation.w is Range
	{
		Atten = 0.f;
	}
	else
	{
		Atten *= 1.f/(g_lights[Index].Attenuation.x + 
			g_lights[Index].Attenuation.y*LD + 
			g_lights[Index].Attenuation.z*LD*LD);
	}
	Out.Ambient *= Atten;
	Out.Diffuse *= Atten;
	Out.Specular *= Atten;
	return Out;
}

//-----------------------------------------------------------------------------
// Name: DoSpotLight()
// Desc: Spot light computation (in eye space)
// P: Position in local space; N: Normal in eye space; V: Viewer in eye space; Index: Light Index
//-----------------------------------------------------------------------------
TripleColor DoSpotLight(float4 P, float3 N, float3 V, int Index, float Glossness)
{
	float3 L = mul(normalize((
		g_lights[Index].Pos-(float3)mul(P, g_matWorld))), 
		(float3x3)g_matViewIT);
	TripleColor Out;
	float NdotL = dot(N, L);
	//Ambient
	Out.Ambient = g_lights[Index].AmbColor;
	//Diffuse
	Out.Diffuse = max(NdotL, 0.0f) * g_lights[Index].DiffColor;
	//Specular    
	float3 H = normalize(L + V);   //half vector
	Out.Specular = 0;
    	if(NdotL>=0.0f)
    	{
		Out.Specular += pow(max(0, dot(H, N)), Glossness) * g_lights[Index].SpecColor;
	}
	float AttenSpot = 1.f;
	float LD = length(g_lights[Index].Pos-(float3)mul(P, g_matWorld));
	if(LD > g_lights[Index].Attenuation.w)
	{
		AttenSpot = 0.f;
	}
	else
	{
		AttenSpot *= 1.f/(g_lights[Index].Attenuation.x + g_lights[Index].Attenuation.y*LD + 
			g_lights[Index].Attenuation.z*LD*LD);
	}
	
	//spot cone computation
	float3 L2 = mul(g_lights[Index].Dir, (float3x3)g_matViewIT);
	float Rho = dot(L, L2);
	AttenSpot *= pow(saturate((Rho - g_lights[Index].Spot.y)/(g_lights[Index].Spot.x - g_lights[Index].Spot.y)), 1.0f);
		//g_lights[Index].Spot.z);
	Out.Ambient *= AttenSpot;
	Out.Diffuse *= AttenSpot;
	Out.Specular *= AttenSpot;
	return Out;
}
#endif 

//-----------------------------------------------------------------------------
// Name: CalcLighting
// Desc: Calculate the lighting for each vertex
//-----------------------------------------------------------------------------
TripleColor CalcLighting(float3 Pos, float3 Viewer, float3 ViewNormal, 
			float4 Emissive, float4 Ambient, float4 Diffuse, 
			float4 Specular, float Glossness, float Opacity
#ifdef SHADOWS
			,inout float4 shadowD, inout float4 shadowS
#endif
			)
{
	TripleColor Color;
	//Emissive and Ambient lights
	Color.Diffuse = Emissive;
	Color.Specular = 0;
	float4 LocalPos = float4(Pos,1.0f);
	//directional lights
	[loop] for(int i = 0; i < g_numDirLight; i++)
	{
//		if(i>=g_numDirLight) break;

		TripleColor ColOut = DoDirLight(ViewNormal, Viewer, i, Glossness);
		Color.Diffuse += ColOut.Ambient*Ambient +ColOut.Diffuse*Diffuse;
		Color.Specular += ColOut.Specular*Specular;
#ifdef SHADOWS
			if (i == 0)
			{
        		shadowD = ColOut.Diffuse*Diffuse;
        		shadowS = ColOut.Specular*Specular;
        		Color.Diffuse -= shadowD;
			Color.Specular -= shadowS;
			}
#endif

	}
	
#ifdef ALLLIGHTTYPES
	int Stride = g_numDirLight;
	//point lights
	[loop] for(int j = 0; j < g_numPointLight; j++)
	{
//		if(j>=g_numPointLight) break;

		TripleColor ColOut = DoPointLight(LocalPos, ViewNormal, Viewer, j+Stride, Glossness);
		Color.Diffuse += ColOut.Ambient*Ambient +ColOut.Diffuse*Diffuse;
		Color.Specular += ColOut.Specular*Specular;

	}
	Stride = g_numDirLight+g_numPointLight;
	//spot lights
	[loop] for(int k = 0; k < g_numSpotLight; k++)
	{
//		if(k>=g_numSpotLight) break;

		TripleColor ColOut = DoSpotLight(LocalPos, ViewNormal, Viewer, k+Stride, Glossness);
		Color.Diffuse += ColOut.Ambient*Ambient +ColOut.Diffuse*Diffuse;
		Color.Specular += ColOut.Specular*Specular;

	}
#endif 

	Color.Diffuse.w = Opacity;//Opacity
	Color.Specular.w = 0;
	return Color;
}
#endif //NONORMAL
#endif //LIGHTING

#ifdef DIFFUSE_TEXTURE
#define TEX_COORD_SPECIFY			0
#define TEX_COORD_POSITION			1
#define TEX_COORD_NORMAL			2
#define TEX_COORD_CAMERASPACEPOSITION		3
#define TEX_COORD_CAMERASPACENORMAL		4	
#define TEX_COORD_CAMERASPACEREFLECTIONVECTOR	5

#define TEX_OP_DISABLE				0
#define TEX_OP_DIFFUSE				1
#define TEX_OP_DECAL				2
#define TEX_OP_MODULATE				3
#define TEX_OP_MIX				4

//Diffuse texture
Texture2D gDiffTex				: DiffuseTexture =NULL;
cbuffer cbTextures
{
	int g_texOpType				: TexOpMode = TEX_OP_DISABLE;
	int g_texCoordType			: TexCoordMode = TEX_COORD_SPECIFY;
	float4x4 g_matDiffTex			: DiffuseTexCoordTransMatrix=	
	{
		{1.0f, 0.0f, 0.0f, 0.0f},
		{0.0f, 1.0f, 0.0f, 0.0f},
		{0.0f, 0.0f, 1.0f, 0.0f},
		{0.0f, 0.0f, 0.0f, 1.0f}
	} ; 
};

bool    gTextureOnOff : TextureOnOff = true;
float4  gAverageColor : AverageColor = float4(1.0f,1.0f,1.0f,1.0f);
	
//sampler for various textures
SamplerState gDiffSamp:DiffuseSampler 
//{
//	Filter   = MIN_MAG_MIP_LINEAR;
//	AddressU = Wrap;
//	AddressV = Wrap;
//}
;

void CalcDiffuseTexture(inout VSOutput Out)
{
	float4 diffuse;
    if (gTextureOnOff)             
	    diffuse = gDiffTex.Sample(gDiffSamp, Out.Tex.xy);
    else 
        diffuse = gAverageColor;
	if((g_texOpType == TEX_OP_DISABLE) || (g_texOpType == TEX_OP_DIFFUSE))
	{
		return;
	}
	
	if(g_texOpType == TEX_OP_DECAL)
	{
		Out.ColorD = diffuse;
		return;
	}
	
	if(g_texOpType == TEX_OP_MODULATE)
	{
		Out.ColorD *=diffuse;
		return;
	}
	
	if(g_texOpType == TEX_OP_MIX)
	{
		Out.ColorD.w = diffuse.w;
		return;
	}
}
#endif

SamplerState gEnvSamp:EnvSampler
//{
//    Filter = MIN_MAG_MIP_LINEAR;
//    AddressU = Wrap;
//    AddressV = Wrap;
//    AddressW = Wrap;
//}
;
SamplerState gEnvSamp2D : EnvSampler2D;

#ifdef IBL
// When IBL is enabled, gEnvTexture would be used to hold the sharp environment texture
TextureCube		gGlossyEnvTex		: glossytexture =NULL;
float3			gGlossGain          : glossgain =float3(1.0f,1.0f,1.0f);
float3			gSharpGain          : envgain =float3(1.0f,1.0f,1.0f);
float3			gAmbGain			: ambgain =float3(1.0f,1.0f,1.0f);
TextureCube	    gAmbEnvTex			: ambienttexture = NULL;
TextureCube		gEnvTex				: EnvironmentTexture =NULL;
float4x4    g_matIBLMat			: IBLTransform = 
{
	{1.0f, 0.0f, 0.0f, 0.0f},
	{0.0f, 1.0f, 0.0f, 0.0f},
	{0.0f, 0.0f, 1.0f, 0.0f},
	{0.0f, 0.0f, 0.0f, 1.0f}
};

void CalcIBLEnvTexture(inout VSOutput Out,float4 specCoef,float4 diffCoef, float glossy, float3 Nw, float3 Vw)
{
	 //For ambient environment image
	 float3 NL = mul(float4(Nw,1.0f), g_matIBLMat).xyz;
	 float3 amb=diffCoef.xyz*gAmbEnvTex.Sample(gEnvSamp, NL).xyz*gAmbGain*0.5f;
	 float NV=dot(Nw, Vw);
	 float3 reflDir=2.0f*NV*Nw-Vw;
	 //It is needed to be careful for IBL matrix. Because IBL texture coordinate is a vector.
	 //For example, there is a rotation M for IBL. MatIBL should be transpose inverse M.
	 reflDir=mul(float4(reflDir,1.0f), g_matIBLMat).xyz;
	 //calculate fresnel factor
	 float f = lerp(0.05f, 1.0f, pow(1.0f - abs(NV), 5.0f)); 
	 float3 specular = specCoef.xyz*(f*gGlossyEnvTex.Sample(gEnvSamp, reflDir).xyz*gGlossGain*0.5f
	 +gEnvTex.Sample(gEnvSamp, reflDir).xyz*gSharpGain*0.5f*glossy);
	 Out.ColorD.xyz += amb;
	 Out.ColorD.xyz = Out.ColorD.xyz * (1-glossy);
	 Out.ColorS.xyz += specular;
}
#endif //IBL

#ifndef IBL
#ifdef ENVIRONMENT_TEXTURE
cbuffer cbEnvTex
{
	//bool     g_EnvEnabled           :EnironmentTexEnabled=false;
	float4x4 g_matEnvTex			: EnvironmentTexCoordTransMatrix = 
	{
		{1.0f, 0.0f, 0.0f, 0.0f},
		{0.0f, 1.0f, 0.0f, 0.0f},
		{0.0f, 0.0f, 1.0f, 0.0f},
		{0.0f, 0.0f, 0.0f, 1.0f}
	};	
}
// Environment texture.
TextureCube		gEnvTex				: EnvironmentTexture =NULL;
Texture2D		gEnvTex2D			: EnvironmentTexture2D = NULL;
TextureCube	    gReflectionMap		: ReflectionMap = NULL;
bool bEnvironmentMap2D : EnvironmentMap2D = false;

float4x4    g_matReflectionMap			: ReflectionMapTransMatrix = 
{
	{1.0f, 0.0f, 0.0f, 0.0f},
	{0.0f, 1.0f, 0.0f, 0.0f},
	{0.0f, 0.0f, 1.0f, 0.0f},
	{0.0f, 0.0f, 0.0f, 1.0f}
};	

#define M_PI 3.14159265f
void CalcEnvironmentTexture(inout VSOutput Out,float4 specCoef,float refBlend)
{
	float4 clrEnvTex;
#ifdef REFLECTIONMAP
	clrEnvTex = gReflectionMap.Sample(gEnvSamp, Out.EnvTex.xyz) * specCoef;
#else
	if (bEnvironmentMap2D)
		clrEnvTex = gEnvTex2D.Sample(gEnvSamp2D,  Out.EnvTex.xy*0.5f + 0.5f) * specCoef;
	else 
		clrEnvTex = gEnvTex.Sample(gEnvSamp, Out.EnvTex.xyz) * specCoef;
#endif
	Out.ColorD = lerp(Out.ColorD, clrEnvTex, refBlend);
}

#endif //Environment texture
#endif //IBL

//-----------------------------------------------------------------------------
// Name: CalcFogFactor
// Desc: Calculate the fog factor for one vertex
//-----------------------------------------------------------------------------
float CalcFogFactor(float FogDist)
{
	float FogFactor = 1.0f;
	if(g_fogMode == FOGMODE_LINEAR)
	{
		FogFactor = (g_fogRange.y - FogDist)/(g_fogRange.y - g_fogRange.x);
	}
	else if(g_fogMode == FOGMODE_EXP)
	{
		FogFactor = 1.f/exp(FogDist * g_fogRange.z);
	}
	else if(g_fogMode == FOGMODE_EXP2)
	{
		FogFactor = 1.f/exp(pow(FogDist * g_fogRange.z, 2));
	}
	return clamp( FogFactor, 0, 1 );
}
