//Settings//
#include "/lib/settings.glsl"

//Varyings//

varying vec2 texCoord;
varying vec3 sunVec, upVec;

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

	//Uniforms//
	uniform int isEyeInWater;
	uniform float frameTimeCounter;
	uniform float blindFactor;
	uniform float rainStrengthS;
	uniform float screenBrightness;
	uniform float viewWidth, viewHeight;
	uniform float far;
	uniform ivec2 eyeBrightnessSmooth;

	uniform vec3 skyColor;
	uniform vec3 cameraPosition;

	uniform sampler2D colortex0;
	uniform sampler2D colortex1;

	uniform mat4 gbufferProjectionInverse;

	//Optifine Constants//
	#if !(LIGHT_SHAFT_QUALITY == 2)
		const bool colortex1MipmapEnabled = true;
	#endif

	//Common Variables//
	float eBS               = eyeBrightnessSmooth.y / 240.0;
	float eBS2              = clamp01(pow(eBS,8.0));
	float eBS3              = clamp((eyeBrightnessSmooth.y-220)/15.0,1.0,1.0);
	float sunVisibility     = clamp00125(dot( sunVec,upVec) + 0.0625) * 8.0;
	float sunVisibilityLSM  = clamp(dot( sunVec,upVec) + 0.001, 0.0, 0.002);
	float moonVisibility    = clamp00125(dot( -sunVec,upVec) + 0.0625) * 8.0;
	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 = texture(colortex0,texCoord.xy);

		#if defined (END) && defined LIGHT_SHAFT_END
			vec3 vl  = textureLod(colortex1, texCoord.xy, 1.5).rgb;
			     vl *= vl;
		#else
			#if LIGHT_SHAFT_QUALITY == 1
				float lod = 0.5;
			#elif LIGHT_SHAFT_QUALITY == 2
				float lod = 0.0;
			#endif

				#ifndef MC_GL_RENDERER_GEFORCE
					if (fract(viewHeight / 2.0) > 0.25 || fract(viewWidth / 2.0) > 0.25)
						lod = 0.0;
				#endif

			float offset = 1.0;

			vec3 vl1     = textureLod(colortex1, texCoord.xy + vec2( 0.0,  offset / viewHeight), lod).rgb;
			vec3 vl2     = textureLod(colortex1, texCoord.xy + vec2( 0.0, -offset / viewHeight), lod).rgb;
			vec3 vl3     = textureLod(colortex1, texCoord.xy + vec2( offset / viewWidth,   0.0), lod).rgb;
			vec3 vl4     = textureLod(colortex1, texCoord.xy + vec2(-offset / viewWidth,   0.0), lod).rgb;
			vec3 finalVl = (vl1 + vl2 + vl3 + vl4) * 0.25;
			vec3 vl      = finalVl;

			vl *= vl;
		#endif


		#if defined (OVERWORLD) && defined LIGHT_SHAFT

			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               = max(NdotU, 0.0);
					      NdotU               = 1.0 - NdotU;
					if    (NdotU > 0.5) NdotU = smoothstep(0.0, 1.0, NdotU);

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

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

					vl *= pow2(NdotU);

				#if defined OVERWORLD && defined LIGHT_SHAFT && defined SHINY_SUNRISE
				vec3 dayLightCol = lightCol2 * lightCol2 * lightCol2 ;
				#else
				vec3 dayLightCol = lightCol * lightCol * lightCol;
				#endif

				vec3 nightLightCol =lightCol * lightCol * 20.0;
				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.75);
					     weatherSky*=rainStrengthS;
					     vlColor    =mix(vlColor, weatherSky * 1.0, 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, rainStrengthSp2);



			} else

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

		#endif

		#ifdef END
			vl *= endCol3.rgb * 0.1 * LIGHT_SHAFT_STRENGTH_END;
			vl *= LIGHT_SHAFT_STRENGTH * (1.0 - rainStrengthS * eBS * 0.875) * shadowFade * (1.0 + isEyeInWater*1.5) * (1.0 - blindFactor);
		#else
			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 = 3.0;
			vl *= vlFactor * 1.15;
		#endif

		color.rgb += vl * lightShaftTime;

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

#endif

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

	//Uniforms//

	uniform mat4 gbufferModelView;

	//Common Variables//
	#ifdef OVERWORLD
		float timeAngleM = timeAngle;
	#else
		float timeAngleM = 0.25;
	#endif

	//Program//
	void main(){
		texCoord=gl_MultiTexCoord0.xy;

		gl_Position=ftransform();

		const vec2 sunRotationData=vec2(cos(sunPathRotation * 0.01745329251994), -sin(sunPathRotation * 0.01745329251994));
		float ang                 =fract(timeAngleM - 0.25);
		      ang                 =(ang+(cos(ang * 3.14159265358979) * -0.5 + 0.5 - ang) / 3.0) * 6.28318530717959;
		      sunVec              =normalize((gbufferModelView * vec4(vec3(-sin(ang), cos(ang) * sunRotationData) * 2000.0, 1.0)).xyz);

		upVec=normalize(gbufferModelView[1].xyz);
	}

#endif