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

//Settings//

//#define DEBUG_SKYBASIC

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

#include "/settings/globalSettings.glsl"

//Varyings//
varying vec3 sunVec, upVec;

#if (defined OVERWORLD && !defined NETHER && !defined END)
varying mat3 moonRotMatrix;
#endif

#if ((defined OVERWORLD && !defined NETHER && !defined END) && (defined PLANET ||defined PLANET2))
	varying mat3 planetRotMatrix;
#endif

#if ((defined OVERWORLD && !defined NETHER && !defined END) && defined NEBULA)
	varying mat3 nebulaRotMatrix;
#endif

#if ((defined OVERWORLD && !defined NETHER && !defined END) && defined GALAXY)
	varying mat3 galaxyRotMatrix;
#endif

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

	//Uniforms//
	uniform sampler2D noisetex;

	#if (defined PLANET ||defined PLANET2)
		uniform sampler2D colortex9;
	#endif

	#ifdef NEBULA
		uniform sampler2D colortex10;
	#endif

	#ifdef GALAXY
		uniform sampler2D colortex11;
	#endif

	uniform int frameCounter;
	uniform int isEyeInWater;
	uniform int moonPhase;
	#define UNIFORM_MOONPHASE

	uniform float blindFactor;
	uniform float frameTimeCounter;
	uniform float nightVision;
	uniform float rainStrength;
	uniform float rainStrengthS;

	#ifdef UNDERGROUND_SKY
	uniform float isEyeInCave;
	#endif

	uniform float rainStrengthShiningStars;

	uniform float screenBrightness;
	uniform float eyeAltitude;
	uniform float far;
	uniform float viewWidth, viewHeight;

	#ifndef WEATHER_PERBIOME
		uniform float isCold;
	#endif

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

	uniform ivec2 eyeBrightnessSmooth;

	uniform mat4 gbufferModelView;
	uniform mat4 gbufferModelViewInverse;
	uniform mat4 gbufferProjectionInverse;
	uniform mat4 shadowProjection;
	uniform mat4 shadowModelView;


	uniform vec3 moonPosition;
	uniform vec3 cameraPosition;
	uniform vec3 skyColor;
	uniform vec3 fogColor;

	//Common Variables//
	float eBS              =eyeBrightnessSmooth.y / 240.0;
	float sunVisibility    =clamp00125(dot( sunVec,upVec) + 0.0625) * 8.0;
	float moonVisibility   =clamp00125(dot( -sunVec,upVec) + 0.0625) * 8.0;
	float screenBrightness2=clamp01(screenBrightness);

	vec3 lightVec = sunVec * (1.0 - 2.0 * float(timeAngle > 0.5325 && timeAngle < 0.9675));

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

	float GetNoise(vec2 pos){
	return fract(sin(dot(pos,vec2(12.9898,4.1414)))*43758.5453);
	}

	vec3 RoundSunMoon(vec3 nViewPos, vec3 sunColor, vec3 moonColor, float NdotU, float VoL){

		const float sunSize = SUNSIZE * 0.333;

		float isMoon = float(VoL < 0.0);

		#ifdef REAL_SUNSIZE
			float sun = pow(abs(VoL), SUNSIZE * isMoon + sunSize * (1 - isMoon));
		#else
			float sun = pow(abs(VoL), SUNSIZE * isMoon + SUNSIZE * (1 - isMoon));
		#endif

		if (isMoon > 0.0) {
			if (moonPhase >= 1) {
				float moonPhaseOffset =float(!(moonPhase == 4));
				if    (moonPhase > 4) moonPhaseOffset *= -1.0;

				float ang             =fract(timeAngle - (0.25 + 0.0075 * moonPhaseOffset * 1650.0 / SUNSIZE));
				      ang             =(ang + (cos(ang * PI) * -0.5 + 0.5 - ang) * 0.333) * TAU;
				vec2  sunRotationData2=vec2(cos(sunPathRotation * 0.01745329251994), -sin(sunPathRotation * 0.01745329251994));
				vec3  rawSunVec2      =(gbufferModelView * vec4(vec3(-sin(ang), cos(ang) * sunRotationData2) * 2000.0 , 1.0)).xyz;
				float moonPhaseVoL    =dot(nViewPos, normalize(rawSunVec2.xyz));
				      moonPhaseVoL    =pow(abs(moonPhaseVoL), SUNSIZE * 0.30);
				      sun             =mix(sun, 0.0, min(moonPhaseVoL * 3.0, 1.0));
			}

		}

		#ifdef HORIZON_SUN_MOON
			float horizonFactor = clamp01((NdotU + 0.0025) * 20.0);
			sun *= horizonFactor;
			moonColor *= 1.0 - sunVisibility;
			sunColor *= sunVisibility;
		#endif

		vec3 sunMoonCol=mix(moonColor * moonVisibility, sunColor * sunVisibility, float(VoL > 0.0));

		vec3 finalSunMoon=sun * sunMoonCol * 32.0;
		     finalSunMoon=pow(finalSunMoon, vec3(2.0 - min(finalSunMoon.r + finalSunMoon.g + finalSunMoon.b, SUN_MOON_FADING)));

			if (isMoon > 0.0) finalSunMoon = min(finalSunMoon, vec3(1.0));

		return finalSunMoon;
	}

	//Includes//

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

	#ifdef OVERWORLD

		#ifdef AURORA
			#include "/lib/atmospherics/aurora.glsl"
		#endif

	#endif

	#include "/lib/color/skyColor.glsl"
	#include "/lib/util/dither.glsl"

	#if (defined OVERWORLD && !defined NETHER && !defined END)
	#include "/lib/atmospherics/lunar.glsl"
	#endif

	#include "/lib/atmospherics/sky.glsl"
	#include "/lib/util/spaceConversion.glsl"

	#ifdef OVERWORLD

		#if REALISTIC_CLOUDS == 1
		#include "/lib/atmospherics/ovclouds.glsl"
		#endif

		#ifdef STARS
		#include "/lib/atmospherics/stars.glsl"
		#endif

		#ifdef SHININGSTARS
		#include "/lib/atmospherics/shiningstars.glsl"
		#endif

		#ifdef SHOOTING_STARS
		#include "/lib/atmospherics/shootingstars.glsl"
		#endif

		#if (ROUND_SUN_MOON > 0 || defined SUN_RAYS)
		#include "/lib/color/sunmoonColor.glsl"
		#include "/lib/atmospherics/sunrays.glsl"
		#endif

		#ifdef CHILD_BIRD_DRAWING
		#include "/lib/atmospherics/skyBirds.glsl"
		#endif

		#if MC_VERSION >= 11605
		#if (defined PLANET || defined PLANET2 || defined NEBULA || defined GALAXY)
		#include "/lib/atmospherics/skyimage.glsl"
		#endif
		#endif

		#ifdef SUNGLARE
		#include "/lib/atmospherics/sunGlare.glsl"
		#endif

	#endif

	//Program//
	void main(){
		vec3 albedo = vec3(0.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;

		vec4 cloud = vec4(1.0);
		vec3 worldPos = ViewToWorld(viewPos.xyz);

		vec3 nViewPos = normalize(viewPos.xyz);
		float NdotU = dot(nViewPos, upVec);

		float cloudMask = 0.0;

		float dither = InterleavedGradientNoise();
			  dither = animateDither(dither);

		#if (REALISTIC_CLOUDS == 1 && defined OVERWORLD)
			cloud = DrawCloud(viewPos.xyz, dither, lightCol, ambientCol, 6);
			cloudMask = min((cloud.a / (CLOUD_OPACITY * 2.20)), 0.25) + (cloud.a / (CLOUD_OPACITY * 2.20)) * 0.5;
		#endif

		#ifdef OVERWORLD
				albedo = GetSkyColor(viewPos.xyz,false);

				float VoL = dot(nViewPos, sunVec);

				#ifdef WHITE_WORLD
					#ifdef SKYW
						albedo.rgb = vec3(0.5);
					#endif
				#endif

				#ifdef BLACK_WORLD
					#ifdef SKYW
						albedo.rgb = vec3(0.0);
					#endif
				#endif

				#if ROUND_SUN_MOON > 0
					vec3 sunColor = sunCol.rgb;
					vec3 moonColor = moonCol.rgb;

					vec3 roundSunMoon = RoundSunMoon(nViewPos, sunColor, moonColor, NdotU, VoL);
					#if REALISTIC_CLOUDS == 1
						roundSunMoon *= Max0(1.0 - cloudMask * (rainStrengthShiningStars + 1.0)) * (1.0 - rainStrengthShiningStars);
					#else
						roundSunMoon *= 1.0 - max(rainStrengthS, rainStrengthShiningStars);
					#endif

						albedo.rgb += mix(roundSunMoon * MOON_I, roundSunMoon * SUN_I, sunVisibility);

				#endif

				#if (ROUND_SUN_MOON > 0 && defined SUN_RAYS)
					albedo.rgb = sunRays(albedo.rgb, worldPos, NdotU);
				#endif

				vec4 wpos = gbufferModelViewInverse * viewPos;
				wpos /= wpos.w;
				float alt = normalize(wpos.xyz).y;
				wpos.xyz = getLunarCoord(wpos.xyz);

				#if HORIZON_MIRROR_REFLECTION == 1
				float altfade = clamp01(alt/0.4 - 0.1);
				#else
				float altfade = clamp01(alt/0.4);
				#endif

				vec3 starcolor = albedo.rgb;

				#if MC_VERSION >= 11605
					#ifdef NEBULA
						starcolor.rgb = drawNebulaImage(starcolor.rgb, vec2(0.2 * NEBULA_SIZE_X, 0.2 * NEBULA_SIZE_Y), wpos.xyz, colortex10, NEBULA_OPACITY);
					#endif
				#endif

				#ifdef STARS
					vec3 starsAlbedo = starcolor.rgb;
					DrawStars(starsAlbedo.rgb, viewPos.xyz);
					starcolor.rgb = mix(starcolor.rgb, starsAlbedo, clamp01(1.0 - cloudMask * CLOUD_OPACITY * 2.2));
				#endif

				#ifdef SHININGSTARS
					if(alt > 0.0){
						starcolor.rgb = DrawConstellations(starcolor.rgb, wpos.xyz, dither, 10.0);
					}
				#endif

				#if MC_VERSION >= 11605
					#if (defined PLANET || defined PLANET2)
					starcolor.rgb = drawPlanetImage(starcolor.rgb,albedo.rgb, vec2(0.2 * PLANET_SIZE_X, 0.2 * PLANET_SIZE_Y), wpos.xyz, colortex9, PLANET_OPACITY);
					#endif

					#ifdef GALAXY
					if (moonVisibility > 0.0){
					starcolor.rgb = drawGalaxyImage(starcolor.rgb, vec2(0.2 * GALAXY_SIZE_X, 0.2 * GALAXY_SIZE_Y), wpos.xyz, colortex11, GALAXY_OPACITY);
					}
					#endif

				#endif

			albedo.rgb = mix(albedo.rgb, clamp01(starcolor.rgb), (1.0-rainStrengthShiningStars) * altfade * clamp01(1.0 - cloudMask * CLOUD_OPACITY * 2.20));

			#ifdef AURORA
				if (moonVisibility > 0.0){
					#ifdef OLD_AURORA_NOISE
						int auroraQ = 24;
					#else
						int auroraQ = 60;
					#endif

					albedo.rgb += clamp01((1.0 - cloudMask * CLOUD_OPACITY * 2.20) * DrawAurora(viewPos.xyz, dither, auroraQ));
				}
			#endif

			#ifdef SHOOTING_STARS
				if (moonVisibility > 0.0){
					vec3 starAlbedo = albedo.rgb;
					#if NUM_SHOOTING_STARS >= 1
						starAlbedo = mix(starAlbedo, DrawShootingStar(albedo.rgb, viewPos.xyz, 1.0, dither), 1.0 - cloudMask);
					#elif NUM_SHOOTING_STARS >= 2
						starAlbedo = mix(starAlbedo, DrawShootingStar(albedo.rgb, viewPos.xyz, 1.2, dither), 1.0 - cloudMask);
					#elif NUM_SHOOTING_STARS >= 3
						starAlbedo = mix(starAlbedo, DrawShootingStar(albedo.rgb, viewPos.xyz, 1.4, dither), 1.0 - cloudMask);
					#elif NUM_SHOOTING_STARS >= 4
						starAlbedo = mix(starAlbedo, DrawShootingStar(albedo.rgb, viewPos.xyz, 1.6, dither), 1.0 - cloudMask);
					#endif
					albedo.rgb = starAlbedo;
				}
			#endif

			#if REALISTIC_CLOUDS == 1
				albedo.rgb = mix(albedo.rgb, cloud.rgb, cloud.a);
			#endif

			#ifdef SUNGLARE
				albedo.rgb  =SunGlare(albedo.rgb, nViewPos, lightColDay);
				albedo.rgb  =MoonGlare(albedo.rgb, nViewPos, lightColNight);
			#endif

			#ifdef CHILD_BIRD_DRAWING
				if (sunVisibility > 0.0){
					vec3 birdColor = albedo.rgb;
					#if NUMBER_OF_BIRDS == 1
						birdColor = drawBirdGroup(birdColor, worldPos,  1.27, 0.45, 1.0);
						birdColor = drawBirdGroup(birdColor, worldPos, -0.81, 0.78, 1.5);
					#elif NUMBER_OF_BIRDS == 2
						birdColor = drawBirdGroup(birdColor, worldPos,  1.27, 0.45, 1.0);
						birdColor = drawBirdGroup(birdColor, worldPos, -0.81, 0.78, 1.5);
						birdColor = drawBirdGroup(birdColor, worldPos,  0.97, 0.12, 0.8);
					#elif NUMBER_OF_BIRDS == 3
						birdColor = drawBirdGroup(birdColor, worldPos,  1.27, 0.45, 1.0);
						birdColor = drawBirdGroup(birdColor, worldPos, -0.81, 0.78, 1.5);
						birdColor = drawBirdGroup(birdColor, worldPos,  0.97, 0.12, 0.8);
						birdColor = drawBirdGroup(birdColor, worldPos, -1.14, 0.50, 1.1);
					#endif
					float sunsetFade = max(timeBrightness + 0.1, (2.0 * sunVisibility));
					albedo.rgb =mix(albedo.rgb, birdColor, (1.0 - rainStrength) * sunsetFade);
				}
			#endif

			albedo.rgb *= 1.0 + nightVision;

			#ifdef CLASSIC_EXPOSURE
				albedo.rgb *= 4.0 - 3.0 * eBS;
			#endif

		#endif

		#ifdef UNDERGROUND_SKY
			albedo.rgb *= 1.0 - isEyeInCave;
		#endif

		#if (defined ENABLE_DARKNESS_EFFECT && MC_VERSION >= 11900)
			if (darknessFactor > 0.001) albedo.rgb = mix(albedo.rgb, darknessColor, darknessFactor);
		#endif

		/*DRAWBUFFERS:0*/

		#ifdef DEBUG_SKYBASIC
            gl_FragData[0]=vec4(1.0, 0.0, 0.5843, 0.75);
		#else
			gl_FragData[0] = vec4(albedo.rgb, 0.1);
		#endif

		#if (REALISTIC_CLOUDS == 1 && defined OVERWORLD)

		/*DRAWBUFFERS:04*/
		gl_FragData[1]=vec4(cloud.a, 0.0, 0.0, 0.0);
		#endif
	}

#endif

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

	//Uniforms//
	uniform int frameCounter;

	//Includes//

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

	//Program//
	void main(){

		vec2 sunRotationData = getSunRotationData();
		vec3 usunvec = getUsunvec(sunRotationData);
		sunVec = getSunVec(usunvec, sunRotationData);

		#if (defined OVERWORLD && !defined NETHER && !defined END)
		moonRotMatrix = getMoonRotMatrix(usunvec);
		#endif

		#if ((defined OVERWORLD && !defined NETHER && !defined END) && (defined PLANET || defined PLANET2))
			planetRotMatrix = rotmat(PLANET_ROTX, PLANET_ROTY, PLANET_ROTZ);
		#endif

		#if ((defined OVERWORLD && !defined NETHER && !defined END) && defined NEBULA)
			nebulaRotMatrix = rotmat(NEBULA_ROTX, NEBULA_ROTY, NEBULA_ROTZ);
		#endif

		#if ((defined OVERWORLD && !defined NETHER && !defined END) && defined GALAXY)
			galaxyRotMatrix = rotmat(GALAXY_ROTX, GALAXY_ROTY, GALAXY_ROTZ);
		#endif

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

		gl_Position=ftransform();

		vec3 color = gl_Color.rgb;

	}

#endif