
#ifndef ATMOSPHERE
#define ATMOSPHERE

#include "AtmosphereFunctions.hlsl"

//---------------------------------------------Height Fog--------------------------------------------------------


half4  heightFogColor;
half   heightFalloff;
half   groundOffset;
half   heightFogStart;
half   heightFogEnd;
half   heightFogDensity;

float BeersLaw(float alpha, float dist)
{
	return exp(-alpha * dist);
}

float ComputeFogAttenuation(float3 worldPos, float3 viewDir, float heightFalloff)
{
	float attV = heightFalloff * viewDir.y;
	float attZ = heightFalloff * worldPos.y;

	if (abs(attV) <= 0.0000003f)
	{
		attV = 0.00094f;
	}

	return (exp(-attZ) - exp(-attZ - attV)) / attV;
}

inline half TransferHeightFog(float3 wspos)
{
	half fogFac = 0;
	wspos.y -= groundOffset;
	float3 viewDir = _WorldSpaceCameraPos - wspos.xyz;

	//float normalizedDepth = (length(viewDir) - _ProjectionParams.y) / (_ProjectionParams.z - _ProjectionParams.y+0.0000001);
	//float normalizedDepth = lerp(Linear01Depth(pos.z), pos.z, unity_OrthoParams.w);
	//float normalizedDepth = (length(viewDir) - x2m_heightFogStart) / max((x2m_heightFogEnd - x2m_heightFogStart), 0.0000001);

	float s = clamp(length(viewDir) - heightFogStart, 0, heightFogEnd);// max(0, normalizedDepth * (x2m_heightFogEnd - x2m_heightFogStart) - x2m_heightFogStart);
	float viewDensity = heightFogDensity * ComputeFogAttenuation(wspos, viewDir, heightFalloff);

	fogFac = BeersLaw(viewDensity, s);
	return fogFac;
}

half3 ApplyHeightFog(half3 sceneColor, float3 wspos)
{
	half fogFac = TransferHeightFog(wspos);
	//return fogFac.xxx;
	return lerp(heightFogColor.rgb, sceneColor.rgb, saturate(fogFac));
}

struct TwoColourCompositeOutput
{
	half3 add;
	half3 multiply;
};

TwoColourCompositeOutput CompositeAtmospherics(float3 viewdir, float3 lightDir, float depth)
{
	if (depth < 1)
		depth = saturate(depth * _ProjectionParams.z / 10000.0);
	
	TwoColourCompositeOutput res;
	res.add = float3(0, 0, 0);
	res.multiply = float3(0, 0, 0);

	float sine = viewdir.y;
	float dist_rt = sqrt(depth);
	dist_rt = lerp(0.5 / NUM_DISTANCES, 1 - 0.5 / NUM_DISTANCES, dist_rt);
	float2 fade_texc = float2(dist_rt, 0.5 * (1.f - sine));
	//fade_texc.y = lerp(0.5 / NUM_ELEVATIONS, 1 - 0.5 / NUM_ELEVATIONS, fade_texc.y);
	half4 insc = SAMPLE_TEXTURE2D(insc_2d_texture, sampler_insc_2d_texture, fade_texc);
	half3 skyl = SAMPLE_TEXTURE2D(skyl_2d_texture, sampler_skyl_2d_texture, fade_texc).rgb;
	half3 loss = SAMPLE_TEXTURE2D(loss_2d_texture, sampler_loss_2d_texture, fade_texc).rgb;

	
	res.multiply = loss;

	float cos0 = dot(viewdir, lightDir);

	res.add = InscatterFunction(insc, hazeEccentricity, cos0, mieRayleighRatio);
	res.add += skyl;


	return res;
}

half3 ApplyAtmosphericScattering(half3 sceneColor, float3 worldPos, float3 viewDir)
{
	const float3 camToWorld = worldPos.xyz - _WorldSpaceCameraPos.xyz;
	const float l = length(camToWorld.xyz);
	const float depth = l / _ProjectionParams.z;
	TwoColourCompositeOutput inscComposite = CompositeAtmospherics(viewDir, x2m_SunDirSize.xyz, depth);
	half3 col = sceneColor * inscComposite.multiply + inscComposite.add;
	col = ApplyHeightFog(col, worldPos);
	return col;
}

#endif // ATMOSPHERE