// Copyright (c) Valve Corporation, All rights reserved. ======================================================================================================

#ifndef CUBEMAP_FOG_FXC
#define CUBEMAP_FOG_FXC

//-------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "system.fxc"
#include "common_samplers.fxc"

//-------------------------------------------------------------------------------------------------------------------------------------------------------------
CreateTextureCubeWithoutSampler( g_tFogCubeTexture ) : register( t12 ) < Attribute( "CubemapFogTexture" ); SrgbRead( true ); >;
float3 g_vFogCubeColor < Attribute( "CubemapFogColor" ); Default3( 1.0f, 1.0f, 1.0f ); >;

//-------------------------------------------------------------------------------------------------------------------------------------------------------------
float4 CalculateCubemapFog( float3 vPositionWs, float3 vPositionToCameraRayWs )
{
	float flFogDistance = length( vPositionToCameraRayWs );
	float3 vPositionToCameraDirWs = normalize( mul( float4( vPositionToCameraRayWs, 0.0 ), g_matvCubeFogSkyWsToOs ).xyz );

	float flAmount = pow( max( 0.0, flFogDistance * g_flCubeFogScale + g_flCubeFogOffset ), g_flCubeFogExponent );
	flAmount = max( flAmount, pow( max( 0.0, vPositionWs.z * g_flCubeFogHeightScale + g_flCubeFogHeightOffset ), g_flCubeFogHeightExponent ) );

	float flMip = g_flCubeMapSizeLog2 * saturate( 1.0 - flAmount * g_flCubeFogBias );
	float4 vCubeTexel = g_tFogCubeTexture.SampleLevel( g_sTrilinearClamp, vPositionToCameraDirWs.xyz, flMip );
	
	float3 vCubeTint = g_vFogCubeColor.rgb;
	vCubeTexel.rgb *= vCubeTint;

	return float4( vCubeTexel.rgb, saturate( flAmount ) );
}

//-------------------------------------------------------------------------------------------------------------------------------------------------------------
float3 ApplyCubemapFog( float3 vInputColor, float3 vPositionWs, float3 vPositionToCameraWs )
{
	// Check if we're going to have any fog at all (near distance will be Inf if fog is off, same with min height)
	float flFogDistSqr = dot( vPositionToCameraWs, vPositionToCameraWs );
	if ( flFogDistSqr > g_vCubeFogCullingParams.x || vPositionWs.z > g_vCubeFogCullingParams.y )
	{
		float4 vCubemapFog = CalculateCubemapFog( vPositionWs, vPositionToCameraWs );
		return lerp( vInputColor.rgb, vCubemapFog.rgb, vCubemapFog.a );
	}
	return vInputColor;
}

#endif // CUBEMAP_FOG_FXC
