/*//////////////////////////////////////////////////////////////////////////////
//    ##      #####   ######   ######     ##     ####     #######  ##  ##     //
//   ####    ##   ##  # ## #    ##  ##   ####     ##       ##   #  ##  ##     //
//  ##  ##   #          ##      ##  ##  ##  ##    ##       ## #     ####      //
//  ##  ##    #####     ##      #####   ##  ##    ##       ####      ##       //
//  ######        ##    ##      ## ##   ######    ##   #   ## #     ####      //
//  ##  ##   ##   ##    ##      ##  ##  ##  ##    ##  ##   ##   #  ##  ##     //
//  ##  ##    #####    ####    #### ##  ##  ##   #######  #######  ##  ##     //
//----------------------------------------------------------------------------//
//----------------------------------------------------------------------------//
//      #####   ##   ##    ##     #####    #######  ######    #####           //
//     ##   ##  ##   ##   ####     ## ##    ##   #   ##  ##  ##   ##          //
//     #        ##   ##  ##  ##    ##  ##   ## #     ##  ##  #                //
//      #####   #######  ##  ##    ##  ##   ####     #####    #####           //
//          ##  ##   ##  ######    ##  ##   ## #     ## ##        ##          //
//          ##  ##   ##  ######    ##  ##   ## #     ## ##        ##          //
//     ##   ##  ##   ##  ##  ##    ## ##    ##   #   ##  ##  ##   ##          //
//      #####   ##   ##  ##  ##   #####    #######  #### ##   #####           //
/////(BSL Shaders Edit)//////////////////////////////////////By LexBoosT//////*/

//Settings//

#include "/lib/util/fastMath.glsl"

#include "/settings/globalSettings.glsl"

//Varyings//
varying vec2 texCoord;

//Fragment Shader///////////////////////////////////////////////////////////////////////////////////
#ifdef FSH

	//Uniforms//
	uniform int frameCounter;
	uniform int isEyeInWater;
	uniform float frameTimeCounter;
	uniform float blindFactor;
	uniform float rainStrengthS;
	uniform float screenBrightness;
	uniform float viewWidth, viewHeight;
	uniform float nightVision;

	#if defined ENABLE_DARKNESS_EFFECT && MC_VERSION >= 11900
		uniform float darknessFactor;
	#endif

	uniform ivec2 eyeBrightnessSmooth;

	uniform vec3 skyColor;
	uniform vec3 cameraPosition;

	uniform sampler2D colortex0;
	uniform sampler2D colortex1;

	uniform mat4 gbufferProjectionInverse;

	//Optifine Constants//
	const bool colortex1MipmapEnabled = true;

	//Common Variables//

	float eBS               = eyeBrightnessSmooth.y / 240.0;
	float eBS2              = clamp01((eyeBrightnessSmooth.y - 220) * 0.0666);
	float sunVisibility     = calculateSunVisibility(sunVec, upVec);
	float screenBrightness2 = clamp01(screenBrightness);
	float rainStrengthSp2   = rainStrengthS * rainStrengthS;
	float lightShaftTime    = pow(abs(sunVisibility - 0.5) * 2.0, 10.0);

	//Common Functions//
	float GetLuminance(vec3 color){
		return dot(color,vec3(0.299, 0.587, 0.114));
	}

	//Includes//
	#include "/lib/color/dimensionColor.glsl"

	//Program//
	void main(){
		vec4 color = texelFetch(colortex0, texelCoord, 0);
		vec3 vl = vec3(0.0);

		#if ((defined OVERWORLD && defined LIGHT_SHAFT) || (defined END && defined LIGHT_SHAFT_END))

			int lod = 0;

			#ifndef MC_GL_RENDERER_GEFORCE
			if (mod(viewHeight, 2.0) == 0.0 && mod(viewWidth, 2.0) == 0.0)
				lod = 0;
			#endif

			float offset = 1.0;

			ivec2 offsetCoord = ivec2(offset / viewWidth, offset / viewHeight);
			vec3 vl1 = texelFetch(colortex1, texelCoord + ivec2(0.0, offsetCoord.y), lod).rgb;
			vec3 vl2 = texelFetch(colortex1, texelCoord + ivec2(0.0, -offsetCoord.y), lod).rgb;
			vec3 vl3 = texelFetch(colortex1, texelCoord + ivec2(offsetCoord.x, 0.0), lod).rgb;
			vec3 vl4 = texelFetch(colortex1, texelCoord + ivec2(-offsetCoord.x, 0.0), lod).rgb;
			vl = (vl1 + vl2 + vl3 + vl4) * 0.25;

			vl *= vl;

			#if defined ENABLE_DARKNESS_EFFECT && MC_VERSION >= 11900
				vl *= 1.0 - darknessFactor;
			#endif

		#endif

		#if (defined LIGHT_SHAFT && defined OVERWORLD)

			if (isEyeInWater == 0) {

					vec4 screenPos  = vec4(gl_FragCoord.xy / vec2(viewWidth, viewHeight), gl_FragCoord.z, 1.0);
					vec4 viewPos    = gbufferProjectionInverse * (screenPos * 2.0 - 1.0);
					     viewPos   /= viewPos.w;
					vec3 nViewPos   = normalize(viewPos.xyz);

					float NdotU               = dot(nViewPos, upVec);
					      NdotU               = Max0(NdotU);
					      NdotU               = 1.0 - NdotU;
					if    (NdotU > 0.5) NdotU = smoothstep(0.0, 1.0, NdotU);

					#if DIRECTION_LIGHTSHAFT == 2
					NdotU *= NdotU;
					#elif DIRECTION_LIGHTSHAFT == 1
					NdotU *= NdotU;
					NdotU *= NdotU;
					#elif DIRECTION_LIGHTSHAFT == 0
					NdotU *= NdotU;
					NdotU *= NdotU;
					NdotU *= NdotU;
					#endif

					NdotU = mix(NdotU, 1.0, rainStrengthSp2 * 0.75);

					vl *=  pow2(NdotU);

				vec3 dayLightCol = pow2(lightCol);

					 dayLightCol=pow(dayLightCol, vec3(LIGHTSHAFT_CONTRAST_DAY));

				vec3 nightLightCol =pow3(lightCol) * 20.0;
					 nightLightCol =pow(nightLightCol, vec3(LIGHTSHAFT_CONTRAST_NIGHT));

				vec3 vlColor = mix(nightLightCol, dayLightCol, sunVisibility);

				vec3 weatherSky  = weatherCol.rgb * weatherCol.rgb;
					 weatherSky *= GetLuminance(ambientCol / weatherSky) * 1.4;
					 weatherSky *= mix(SKY_RAIN_NIGHT, SKY_RAIN_DAY, sunVisibility);
					 weatherSky  = max(weatherSky, skyColor * skyColor * 0.5625);
					 weatherSky *= rainStrengthS;
					 vlColor = mix(vlColor, weatherSky, rainStrengthSp2);

				#if MC_VERSION >= 11800
				vl *= vlColor * clamp01(exp(2.0 * cameraPosition.y + 126.0));
				#else
				vl *= vlColor * clamp01(exp(2.0 * cameraPosition.y - 2.0));
				#endif

				float rainMult = mix(LIGHT_SHAFT_NIGHT_RAIN_MULTIPLIER * (0.25 + 0.2 * screenBrightness2),
									 LIGHT_SHAFT_DAY_RAIN_MULTIPLIER * (0.65 + 0.2 * screenBrightness2),
									 sunVisibility);

				float timeBrightnessSqrt = sqrt1(timeBrightness);

				vl*=mix(1.0, LIGHT_SHAFT_NOON_MULTIPLIER * 0.75, timeBrightnessSqrt * (1.0 - rainStrengthS * 0.8));
				vl*=mix((LIGHT_SHAFT_NIGHT_MULTIPLIER * 10) * (0.91 - moonBrightness * 0.39), 2.0, sunVisibility);
				vl*=mix(1.0, rainMult * 0.1, rainStrengthSp2);

			} else {

				vl *= length(lightCol) * LIGHT_SHAFT_UNDERWATER_MULTIPLIER * 0.005 * (1.0 - rainStrengthS * 0.85);
			}

		#endif

		#if (defined LIGHT_SHAFT_END && defined END)
			vl *= endColSqrt3.rgb * 0.025 * LIGHT_SHAFT_STRENGTH_END;
			vl *= LIGHT_SHAFT_STRENGTH * (1.0 - rainStrengthS * eBS * 0.875) * shadowFade * (1.0 + isEyeInWater) * (1.0 - blindFactor);
		#endif

		#if (defined LIGHT_SHAFT && defined OVERWORLD)
			vl *= LIGHT_SHAFT_STRENGTH * shadowFade * (1.0 - blindFactor);

			float vlFactor = (1.0 - min((timeBrightness) * 2.0, 0.75));
				  vlFactor = mix(vlFactor, 0.05, rainStrengthS);
			if (isEyeInWater == 1) vlFactor = 4.0;
			vl *= vlFactor * 1.15;
		#endif

		if (nightVision > 0.0) {
			vl = vec3(0.0, length(vl), 0.0);
		}

		#if ((defined OVERWORLD && defined LIGHT_SHAFT) || (defined END && defined LIGHT_SHAFT_END))
			color.rgb += vl * lightShaftTime;
		#endif

		/*DRAWBUFFERS:0*/
		gl_FragData[0] = vec4(Max0(color));
	}

#endif

//Vertex Shader/////////////////////////////////////////////////////////////////////////////////////
#ifdef VSH

	//Program//
	void main(){
		texCoord = (gl_TextureMatrix[0] * gl_MultiTexCoord0).xy;

		gl_Position=ftransform();

		upVec=normalize(gbufferModelView[1].xyz);
		vec2 sunRotationData = getSunRotationData();
		vec3 usunvec = getUsunvec(sunRotationData);
		sunVec = getSunVec(usunvec, sunRotationData);
	}

#endif