#include "common.h"

// Check Modules
#include "check_screenspace.h"

#undef ULTRA_SHADOWS_ON
#undef USE_ULTRA_SHADOWS

#define RAY_PATH 2.0h
#define JITTER_TEXTURE_SIZE	64.0f

#ifdef	SUN_SHAFTS_QUALITY
	#if SUN_SHAFTS_QUALITY==1
		#define	FILTER_LOW
		#define RAY_SAMPLES	15
	#elif SUN_SHAFTS_QUALITY==2
		#define RAY_SAMPLES	25
	#elif SUN_SHAFTS_QUALITY==3
		#define RAY_SAMPLES	30
	#endif
#endif

#ifndef	FILTER_LOW
#ifdef USE_MINMAX_SM
#define SM_MINMAX
#endif
#endif

#include "shadow.h"

float4 volume_range; //	x - near plane, y - far plane
float4 sun_shafts_intensity;

#ifdef MSAA_OPTIMIZATION
float4 	main (v2p_volume  I, uint iSample : SV_SAMPLEINDEX  ) : SV_Target
#else
float4 	main (v2p_volume  I) : SV_Target
#endif
{
#ifndef	SUN_SHAFTS_QUALITY
	return float4(0,0,0,0);
#else	//	SUN_SHAFTS_QUALITY

	float2	tc  = I.tc.xy / I.tc.w;
	float4	pos2d = I.hpos;

	float ResScale = 1.0f;

	pos2d *= ResScale;
	
	gbuffer_data gbd = gbuffer_load_data( GLD_P(tc, pos2d, ISAMPLE) );
	float3	P = gbd.P;

	// Variable ray length, variable step dencity, use jittering
	float4	J0 	= jitter0.Sample( smp_jitter, tc * (screen_res.x / ResScale ) * 1.0 / JITTER_TEXTURE_SIZE );
	float	coeff = (RAY_SAMPLES - 1*J0.x)/(RAY_SAMPLES*RAY_SAMPLES);		
	float3	direction = P*coeff;

	float	depth = P.z;
	float	deltaDepth = direction.z;
	
	float4	current	= mul (m_shadow,float4(P,1.0));
	float4	delta 	= mul (m_shadow, float4(direction,0.0));

	float	res = 0.0;
	float	max_density = sun_shafts_intensity;
	float	density = max_density/RAY_SAMPLES;

	// SUN VOLUMETRIC FIXES - SSS Update 14.7
	// - Added weapon fade
	// - Discard out of bound shadow map sampling
	// - Fade volumetric edge
	// https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders/

	// Volumetric offset when used with SSS extended shadows.
	current.z += 0.001f;

	// Fade Weapon
	density *= saturate(depth * 0.8f);

	if (depth < 0.0001)
		res = max_density;

	[unroll (RAY_SAMPLES)]
	for ( int i=0; i<RAY_SAMPLES; ++i )
	{
		// Don't sample out of bounds
		if (current.x >= 0 && current.x <= 1 && current.y >= 0 && current.y <= 1)
		{
			if (depth > 0.1f)
				res += density * sample_hw_pcf(current, float4(0.0,0.0,0.0,0.0));
		}

		depth -= deltaDepth;
		current -= delta;
	}

	float fSturation = -Ldynamic_dir.z;

	//	Normalize dot product to
	fSturation = 0.5*fSturation+0.5;
	//	Map saturation to 0.2..1
	fSturation = 0.80*fSturation+0.20;

	res *= fSturation;

	// Use fog near/far to fade the sun rays
	float fog = saturate(length(P) * fog_params.w + fog_params.x);

#ifdef USE_STRICT_GAMMA_CORRECTION
	res = SRGBToLinear(res);
	float3 SunColor = SRGBToLinear(Ldynamic_color.rgb);
#else
	float3 SunColor = Ldynamic_color.rgb;
#endif

	// Fade from "res" to "max_density" using squared fog to get a nice curve
	float3 result = lerp(SunColor * max_density * fSturation, SunColor * res, 1.0f - fog * fog);

	return float4(result, 0);
#endif	//	SUN_SHAFTS_QUALITY
}