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

//Settings//

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

#include "/settings/globalSettings.glsl"

//Varyings//
varying vec2 texCoord;
varying vec3 sunVec, upVec;

//Fragment Shader///////////////////////////////////////////////////////////////////////////////////

#ifdef FSH

	//Uniforms//
	uniform sampler2D colortex0;
	uniform sampler2D colortex1;
	uniform sampler2D depthtex0;
	uniform sampler2D depthtex1;
	uniform sampler2D noisetex;

	#if (!defined OUTLINE_TRIPWIRE && MC_VERSION >= 11605)
		uniform sampler2D colortex8;
	#endif

	uniform int frameCounter;
	uniform int isEyeInWater;

	#ifdef UNDERGROUND_SKY
	uniform float isEyeInCave;
	#endif

	uniform float blindFactor, darknessFactor, nightVision;
	uniform float far, near;
	uniform float frameTimeCounter;
	uniform float rainStrengthS;
	uniform float screenBrightness;
	uniform float viewWidth, viewHeight, aspectRatio;

	uniform ivec2 eyeBrightnessSmooth;

	uniform vec3 cameraPosition;

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

	uniform vec3 fogColor;

	#if ((defined OVERWORLD && defined LIGHT_SHAFT) || (defined END && defined LIGHT_SHAFT_END))
		uniform sampler2DShadow shadowtex0;
		uniform sampler2DShadow shadowtex1;
		uniform sampler2D shadowcolor0;

		const bool generateShadowMipmap = false;
		const bool generateShadowColorMipmap = false;

		const bool shadowcolor0Nearest = false;
		const vec4 shadowcolor0ClearColor = vec4(1.0, 1.0, 1.0, 1.0);
		const bool shadowcolor0Clear = true;

		const bool shadowtex0Mipmap = false;
		const bool shadowtex0Nearest = false;
		const bool shadowHardwareFiltering0 = true;

		const bool shadowtex1Mipmap = false;
		const bool shadowtex1Nearest = false;
		const bool shadowHardwareFiltering1 = true;
	#endif

	//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 GetLinearDepth(float depth) {
		return (2.0 * near) / (far + near - depth * (far - near));
	}

	#if ((defined OVERWORLD && defined LIGHT_SHAFT) || (defined END && defined LIGHT_SHAFT_END))
		float GetDepth(float depth) {
			return 2.0 * near * far / (far + near - (2.0 * depth - 1.0) * (far - near));
		}

		float GetDistX(float dist) {
			return (far * (dist - near)) / (dist * (far - near));
		}

	#endif

	//Includes//
	#if (defined NETHER || defined END)
	#include "/lib/color/lightColor.glsl"
	#endif

	#include "/lib/color/dimensionColor.glsl"
	#include "/lib/color/waterColor.glsl"
	#include "/lib/util/dither.glsl"
	#include "/lib/atmospherics/waterFog.glsl"
	#include "/lib/util/spaceConversion.glsl"

	#if ((defined OVERWORLD && defined LIGHT_SHAFT) || (defined END && defined LIGHT_SHAFT_END))
	#include "/lib/atmospherics/volumetricLight.glsl"
	#endif

	#ifdef OUTLINE_ENABLED
	#include "/lib/color/skyColor.glsl"
	#include "/lib/color/blocklightColor.glsl"
	#include "/lib/outline/outlineOffset.glsl"
	#include "/lib/outline/outlineMask.glsl"
	#include "/lib/atmospherics/sky.glsl"
	#include "/lib/atmospherics/fog.glsl"
	#include "/lib/outline/blackOutline.glsl"
	#endif

	//Program//
	void main(){
		vec4  color      =texelFetch(colortex0, texelCoord, 0);
		vec3  translucent=texelFetch(colortex1, texelCoord, 0).rgb;
		vec3  worldPos   =vec3(0.0);
		vec3  vl         =vec3(0.0);
		float z0         =texelFetch(depthtex0, texelCoord, 0).r;
		float z1         =texelFetch(depthtex1, texelCoord, 0).r;
		bool water = false;

		if (translucent.b > 0.999 && z1 > z0) {
			water = true;
			translucent = vec3(1.0);
		}
		vec4 viewPos = gbufferProjectionInverse * (vec4(texCoord, z0, 1.0) * 2.0 - 1.0);
		viewPos /= viewPos.w;

		#if (defined WATER_REFRACTION && !defined NETHER)

			#if WATER_MODE == 1 || WATER_MODE == 2
				if (isEyeInWater > 0.5){
			#endif
				if (water) {
					worldPos = ViewToWorld(viewPos.xyz);

					vec3 worldPosWF = worldPos + cameraPosition;
					vec2 PosRF = worldPosWF.xz * 0.005 + worldPosWF.y * 0.0025 + 0.0045 * WATER_SPEED * frameTimeCounter;

					float hand = 1.0 - float(z0 < 0.56);
					float d0 = GetLinearDepth(z0);
					float fovScale = gbufferProjection[1][1] / 1.37;
					float ScaleWF = fovScale;

					float distScaleRF = max((far - near) * d0 + near, 14.0);
					ScaleWF *= 2.0 / distScaleRF;

					vec2 NoiseRF = texture2D(noisetex, PosRF).rb;
					NoiseRF.r -= 0.45;
					NoiseRF.g -= 0.58;

					NoiseRF *= vec2(0.07 * hand * ScaleWF);

					float Wateraim = float(texture2D(colortex1, texCoord + NoiseRF).b > 0.999);
					float z0aim = texture2D(depthtex0, texCoord + NoiseRF).r;
					float z1aim = texture2D(depthtex1, texCoord + NoiseRF).r;

					float depthDif = GetLinearDepth(z1aim) - GetLinearDepth(z0aim);
					NoiseRF *= clamp01(depthDif * 150.0);

					if (z0aim >= 0.56 && Wateraim > 0.95) {
					color.rgb = texture2D(colortex0, texCoord + NoiseRF).rgb;

						if (isEyeInWater == 1) {
							translucent = texture2D(colortex1, texCoord + NoiseRF).rgb;
								if (translucent.b < 0.999) {
								translucent = vec3(1.0);
								}
							z0 = texture2D(depthtex0, texCoord + NoiseRF).r;
							z1 = texture2D(depthtex1, texCoord + NoiseRF).r;
						}
					}
				}
			#if WATER_MODE == 1 || WATER_MODE == 2
			}
			#endif
		#endif

		#ifdef OUTLINE_ENABLED
			vec4  outerOutline=vec4(0.0), innerOutline = vec4(0.0);

			float outlineMask = GetOutlineMask();

			if (outlineMask > 0.5 || isEyeInWater > 0.5 ){
			 	Outline(color.rgb, true, outerOutline, innerOutline);
			}

			#if PROMO_OUTLINE_EVERYWHERE > 0
				if(z1 > z0) color.rgb=mix(color.rgb, innerOutline.rgb, innerOutline.a);
			#endif
		#endif

		if (isEyeInWater == 1.0) {
			vec4 waterFog   =GetWaterFog(viewPos.xyz);
			     waterFog.a =mix(waterAlpha * 0.1, 1.0, waterFog.a);
			     color.rgb  =mix(sqrt(color.rgb), sqrt(waterFog.rgb), waterFog.a);
			     color.rgb *=color.rgb;
		}

		#if ((defined OVERWORLD && defined LIGHT_SHAFT) || (defined END && defined LIGHT_SHAFT_END))
			vec3  nViewPos = normalize(viewPos.xyz);
			vec3  vlAlbedo = translucent;

			float cosS = dot(nViewPos, lightVec);
			float dither = 0.0;

		#if TEXTURED_DITHERING == 0
			dither = BlueNoise(gl_FragCoord.xy);
			dither = animateDither(dither);
		#else
			dither = InterleavedGradientNoise();
		#endif

			if    (isEyeInWater == 0 && water) vlAlbedo = vec3(0.0);
			float depth0                                = GetDepth(z0);
			float depth1                                = GetDepth(z1);
			vl = getVolumetricRays(depth0, depth1, vlAlbedo, dither, cosS, vl);
		#else
			vl = vec3(0.0);
		#endif

		#ifdef OUTLINE_ENABLED
			color.rgb = mix(color.rgb, outerOutline.rgb, outerOutline.a);
		#endif

		/*DRAWBUFFERS:01*/
		gl_FragData[0] = vec4(color);
		gl_FragData[1] = vec4(vl, 1.0);

	}

#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
