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

******************************************************************************/

float4x4 worldViewProj : WorldViewProjection;
float4x4 Proj : Projection;
float3 campos : CAMERAPOS;

// Fog parameters
float4 DistanceFogStartColor : DistanceFogStartColor;
float4 DistanceFogEndColor : DistanceFogEndColor;
float  DistanceFogStartDist : DistanceFogStartDist;
float  DistanceFogEndDist : DistanceFogEndDist;
float  DistanceFogExponent : DistanceFogExponent;

float4 HeightFogStartColor : HeightFogStartColor;
float4 HeightFogEndColor : HeightFogStartColor;
float  HeightFogStartHeight : HeightFogStartHeight;
float  HeightFogEndHeight : HeightFogEndHeight;
float  HeightFogExponent : HeightFogExponent;

// Directional Distance fogging
float4 DistanceFogDirectionalEndColor : DistanceFogDirectionalEndColor;
float2 DirectionalFogDir : DirectionalFogDir;
float  DirectionalFalloff : DirectionalFalloff;

float2 UVOffset0 : UVOffset0;
float2 UVOffset1 : UVOffset1;


float NoiseTextureColorShift : NoiseTextureColorShift;
float FogColorShift : FogColorShift;

float UVScale0 : UVScale0;
float UVScale1 : UVScale1;

float2 CameraDir : CameraDir;


texture diffuseTexture : DiffuseTexture;
sampler DiffuseTextureSampler = sampler_state 
{
    texture = <diffuseTexture>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = POINT;
    MINFILTER = POINT;
    MAGFILTER = POINT;
};

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


texture depthTexture : Custom0;
sampler DepthTextureSampler = sampler_state 
{
    texture = <depthTexture>;
    AddressU  = WRAP;        
    AddressV  = WRAP;
    AddressW  = WRAP;
    MIPFILTER = POINT;
    MINFILTER = POINT;
    MAGFILTER = POINT;
};

struct vertexInput {
    float4 position				: POSITION;
    float2 texCoordDiffuse		: TEXCOORD0;
};

struct vertexOutput {
    float4 hPosition		: POSITION;
    float2 texCoordDiffuse	: TEXCOORD0;
};


vertexOutput VS_Screen(vertexInput IN) 
{
    vertexOutput OUT;
    OUT.hPosition = mul( IN.position, Proj );
    OUT.texCoordDiffuse = IN.texCoordDiffuse;
    return OUT;
}


//-----------------------------------
float4 PS_Textured( vertexOutput IN): COLOR
{
    float3 sampled = tex2D( DiffuseTextureSampler, IN.texCoordDiffuse ).xyz;  		
	float4 camToWorld =  tex2D( DepthTextureSampler, IN.texCoordDiffuse );
		
	float distanceToPixel = length(camToWorld.xyz);
	float3 worldPos = -camToWorld.xyz + campos;

	float2 uvNoise0;
	float2 uvNoise1;
	uvNoise0.x = worldPos.x;
	uvNoise0.y = worldPos.z;		
	uvNoise0 *= UVScale0;

	uvNoise1.x = worldPos.x;
	uvNoise1.y = worldPos.z;		
	uvNoise1 *= UVScale1;
	
	uvNoise0 += UVOffset0; //  / UVScale0;
	float4 noiseTexture0 = tex2D( NoiseTextureSampler, uvNoise0 );
	
	uvNoise1 += UVOffset1; // / UVScale1; 
	float4 noiseTexture1 = tex2D( NoiseTextureSampler, uvNoise1 );
	
	float fogFactorDist = (distanceToPixel-DistanceFogStartDist) / (DistanceFogEndDist-DistanceFogStartDist);
	fogFactorDist = saturate( fogFactorDist );	
		
	// exponential ramp up
	fogFactorDist = pow( fogFactorDist, DistanceFogExponent );	
		
	float fogFactorHeight = (worldPos.y-HeightFogStartHeight) / (HeightFogEndHeight-HeightFogStartHeight);			
	fogFactorHeight = saturate( fogFactorHeight );	
	
	// exponential ramp up
	fogFactorHeight = pow( fogFactorHeight, HeightFogExponent );
	fogFactorHeight = 1.0f - fogFactorHeight; // flip
	
	float4 distFogColor = lerp( DistanceFogStartColor, DistanceFogEndColor, fogFactorDist );
	float4 heightFogColor = lerp( HeightFogEndColor, HeightFogStartColor, fogFactorHeight );	
	heightFogColor.xyz += NoiseTextureColorShift + (noiseTexture0.x * noiseTexture1.y);
	heightFogColor.xyz += FogColorShift;
	
   
	float4 mixedFogColor;
	mixedFogColor = lerp( heightFogColor, distFogColor, fogFactorDist );

	float fogMix = heightFogColor.w * (1.0f - fogFactorDist) + fogFactorDist;
		
	// Skip fog?
	if( camToWorld.w < 1.0f )
	{
	    fogMix = 0.0f;
	}
	
	fogMix *= mixedFogColor.a;
	
	float3 outColor = lerp( sampled, mixedFogColor, fogMix );

	return float4( outColor, 1 );
}



//-----------------------------------
float4 PS_DirectionalTextured( vertexOutput IN): COLOR
{
    float3 sampled = tex2D( DiffuseTextureSampler, IN.texCoordDiffuse ).xyz;  		
	float4 camToWorld =  tex2D( DepthTextureSampler, IN.texCoordDiffuse );

	
	float distanceToPixel = length(camToWorld.xyz);
	float3 worldPos = -camToWorld.xyz + campos;

	float2 uvNoise0;
	float2 uvNoise1;
	uvNoise0.x = worldPos.x;
	uvNoise0.y = worldPos.z;		
	uvNoise0 *= UVScale0;

	uvNoise1.x = worldPos.x;
	uvNoise1.y = worldPos.z;		
	uvNoise1 *= UVScale1;
	
	uvNoise0 += UVOffset0; //  / UVScale0;
	float4 noiseTexture0 = tex2D( NoiseTextureSampler, uvNoise0 );
	
	uvNoise1 += UVOffset1; // / UVScale1; 
	float4 noiseTexture1 = tex2D( NoiseTextureSampler, uvNoise1 );
	
	float fogFactorDist = (distanceToPixel-DistanceFogStartDist) / (DistanceFogEndDist-DistanceFogStartDist);
	fogFactorDist = saturate( fogFactorDist );	
		
	// exponential ramp up
	fogFactorDist = pow( fogFactorDist, DistanceFogExponent );	
		
	float fogFactorHeight = (worldPos.y-HeightFogStartHeight) / (HeightFogEndHeight-HeightFogStartHeight);			
	fogFactorHeight = saturate( fogFactorHeight );	
	
	// exponential ramp up
	fogFactorHeight = pow( fogFactorHeight, HeightFogExponent );
	fogFactorHeight = 1.0f - fogFactorHeight; // flip
	
	
	// Directional distance fog:	
	float facing = (1.0f + dot( CameraDir, DirectionalFogDir )) / 2.0f;	
	facing = pow( facing, DirectionalFalloff );
	
	float4 distFogEndColor = lerp( DistanceFogEndColor, DistanceFogDirectionalEndColor, facing );
	float4 distFogColor = lerp( DistanceFogStartColor, distFogEndColor, fogFactorDist );
	
	//float4 distFogColor = lerp( DistanceFogStartColor, DistanceFogEndColor, fogFactorDist );
	float4 heightFogColor = lerp( HeightFogEndColor, HeightFogStartColor, fogFactorHeight );	
	heightFogColor.xyz += NoiseTextureColorShift + (noiseTexture0.x * noiseTexture1.y);
	heightFogColor.xyz += FogColorShift;
	
   
	float4 mixedFogColor;
	mixedFogColor = lerp( heightFogColor, distFogColor, fogFactorDist );

	float fogMix = heightFogColor.w * (1.0f - fogFactorDist) + fogFactorDist;	
	fogMix *= mixedFogColor.a;
	
		
	// Skip fog?
	if( camToWorld.w < 1.0f  )
	{
	    fogMix = 0.0f;
	}
	
	float3 outColor = lerp( sampled, mixedFogColor, fogMix );

	return float4( outColor, 1 );
}


//-----------------------------------
technique basic
{
    pass p0 
    {		
        VertexShader = compile vs_2_0 VS_Screen();
		PixelShader  = compile ps_2_0 PS_Textured();
		cullmode = none;
    }
}



//-----------------------------------
technique directionalDistance
{
    pass p0 
    {		
        VertexShader = compile vs_2_0 VS_Screen();
		PixelShader  = compile ps_2_0 PS_DirectionalTextured();
		cullmode = none;
    }
}

