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

//Settings//

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

#include "/settings/globalSettings.glsl"

#include "/settings/dofSettings.glsl"

//Varyings//
varying vec2 texCoord;

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

	//Uniforms//
	uniform float viewWidth, viewHeight, aspectRatio;

	uniform ivec2 eyeBrightnessSmooth;

	#ifdef DOF
		uniform float centerDepthSmooth;
	#endif

	uniform int frameCounter;

	uniform float frameTimeCounter;
	uniform mat4 gbufferProjection;

	uniform sampler2D colortex0;
	uniform sampler2D depthtex1;

	#ifdef FLOU_EAU
		uniform int isEyeInWater;
	#endif

	#ifdef DISTANCE_BLUR
		uniform sampler2D depthtex0;
		uniform mat4 gbufferProjectionInverse;
	#endif

	#if defined DISTANCE_BLUR || defined RAIN_BLUR_CAM
		uniform float rainStrengthS2;
	#endif

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

	//Common Functions//

	mat2 Rotate(float angle)
	{
		return mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
	}

	#ifdef DOF
	float GetCircleStandardDOF(float z, float centerDepth) {

        #if defined NETHER && (defined DOF || defined DISTANCE_BLUR)
            float DOF_STRENGTH = NETHER_DOF_STRENGTH;
        #endif

        #if defined OVERWORLD && (defined DOF || defined DISTANCE_BLUR)
            float DOF_STRENGTH = OVERWORLD_DOF_STRENGTH;
        #endif

        #if defined END && (defined DOF || defined DISTANCE_BLUR)
            float DOF_STRENGTH = END_DOF_STRENGTH;
        #endif

            float coc = abs(z - centerDepth) / 0.6;

        return coc / (1.0 / DOF_STRENGTH + coc);
    }

	#endif

	//Includes//
	#include "/lib/util/dither.glsl"

	//Common Variables//
	vec2 dofOffsets[18] = vec2[18](
		vec2( 0.0    ,  0.25  ),
		vec2(-0.2165 ,  0.125 ),
		vec2(-0.2165 , -0.125 ),
		vec2( 0      , -0.25  ),
		vec2( 0.2165 , -0.125 ),
		vec2( 0.2165 ,  0.125 ),
		vec2( 0      ,  0.5   ),
		vec2(-0.25   ,  0.433 ),
		vec2(-0.433  ,  0.25  ),
		vec2(-0.5    ,  0     ),
		vec2(-0.433  , -0.25  ),
		vec2(-0.25   , -0.433 ),
		vec2( 0      , -0.5   ),
		vec2( 0.25   , -0.433 ),
		vec2( 0.433  , -0.2   ),
		vec2( 0.5    ,  0     ),
		vec2( 0.433  ,  0.25  ),
		vec2( 0.25   ,  0.433 )
	);

	float eBS = eyeBrightnessSmooth.y / 240.0;

	//Common Functions//

	vec3 DepthOfField(vec3 color, float z){

		float noise = InterleavedGradientNoise();
			#if AA > 1
			noise = fract(noise + frameTimeCounter * 38.34718);

			mat2 rotation = Rotate(noise * 2.0 * 3.1415);
			#endif

		#if defined (NETHER) && (defined DOF || defined DISTANCE_BLUR)
			float DISTANCE_BLUR_STRENGTH = NETHER_DISTANCE_BLUR_STRENGTH;
			float DOF_STRENGTH = NETHER_DOF_STRENGTH;
		#endif

		#if defined (OVERWORLD) && (defined DOF || defined DISTANCE_BLUR)
			float DISTANCE_BLUR_STRENGTH = OVERWORLD_DISTANCE_BLUR_STRENGTH;
			float DOF_STRENGTH = OVERWORLD_DOF_STRENGTH;
		#endif

		#if defined (END) && (defined DOF || defined DISTANCE_BLUR)
			float DISTANCE_BLUR_STRENGTH = END_DISTANCE_BLUR_STRENGTH;
			float DOF_STRENGTH = END_DOF_STRENGTH;
		#endif

		vec3 dof = vec3(0.0);
		float hand = float(z < 0.56);
		float fovScale = gbufferProjection[1][1] / 1.37;
		float fovScale2 = gbufferProjection[1][1] / 2.74;

		#ifdef DISTANCE_BLUR
			float z0         = texture2D(depthtex0, texCoord.xy).r;
			vec4  screenPos  = vec4(texCoord.x, texCoord.y, z0, 1.0);
			vec4  viewPos    = gbufferProjectionInverse * (screenPos * 2.0 - 1.0);
			      viewPos   /= viewPos.w;

			float coc1 = max(min(length(viewPos) * 0.001, 0.1) * DISTANCE_BLUR_STRENGTH * (1.0 + (rainStrengthS2 * eBS * RAIN_BLUR_MULT)) / 256 , 0.001);

		#else

			float coc1 = 0;

		#endif

		#ifdef DOF
			float coc2 = GetCircleStandardDOF(z, centerDepthSmooth);

			#ifdef EXTRA_CIRCULAR_DOF
				float coc2dist = max(clamp(abs(1.0 - centerDepthSmooth), 0.0, 0.002) / EXTRA_CIRCULAR_DOF_STRENGTH * DOF_STRENGTH - 0.001, 0.001);
				float coc2center = max(length((texCoord.xy * 2.0 - 1.0) * vec2(aspectRatio, 1.0)), 0.001);
				coc2 = max(coc2,coc2dist*coc2center);
			#endif

		#else

			float coc2 = 0.0;

		#endif

			float coc = max(coc1,coc2);

		#ifdef FLOU_EAU
			if (float(isEyeInWater) > 0.9) coc = max(FACTEUR_FLOU_EAU / 2.0 ,coc);
		#endif

		#ifdef RAIN_BLUR_CAM
			vec2  spos         = texCoord.xy * 2.0 - 1.0;
			float blurVignette = clamp01(pow(length(spos), RAIN_BLUR_CAM_INTENSITY));
			      coc          = max(coc, rainStrengthS2 * eBS * blurVignette * 20.0);
		#endif

		coc = coc / sqrt(coc * coc + 0.1);
		float chromaOffset = CHROMA_STRENGTH /100.0;
		chromaOffset *= coc;

		if (coc * 0.5 > 1.0 / max(viewWidth, viewHeight) && hand < 0.5){

			for(int i = 0; i < 18; i++) {

				vec2 offset = dofOffsets[i] * coc * 0.0085 * fovScale;

				#if AA > 1
					offset = rotation * offset;
				#endif

				float lod = log2(viewHeight * aspectRatio * coc * 0.75 / 320.0);

				#ifdef CHROMATIC_ABERRATION

					#ifdef OVERWORLD
						#ifdef CHROMATIC_ABERRATION_O
						dof += vec3(texture2DLod(colortex0, texCoord - offset + vec2(chromaOffset * fovScale2, 0.0), lod).r,
									texture2DLod(colortex0, texCoord - (offset * 0.5), lod).g,
									texture2DLod(colortex0, texCoord + offset -vec2(chromaOffset * fovScale2, 0.0), lod).b);
						#endif
					#endif

					#ifdef NETHER
						#ifdef CHROMATIC_ABERRATION_N
						dof += vec3(texture2DLod(colortex0, texCoord - offset + vec2(chromaOffset * fovScale2, 0.0), lod).r,
									texture2DLod(colortex0, texCoord - (offset * 0.5), lod).g,
									texture2DLod(colortex0, texCoord + offset -vec2(chromaOffset * fovScale2, 0.0), lod).b);
						#endif
					#endif

					#ifdef END
						#ifdef CHROMATIC_ABERRATION_E
						dof += vec3(texture2DLod(colortex0, texCoord - offset + vec2(chromaOffset * fovScale2, 0.0), lod).r,
									texture2DLod(colortex0, texCoord - (offset * 0.5), lod).g,
									texture2DLod(colortex0, texCoord + offset -vec2(chromaOffset * fovScale2, 0.0), lod).b);
						#endif
					#endif

				#else
					dof += texture2DLod(colortex0, texCoord + offset, lod).rgb;
				#endif
			}
			dof /= 18;
		}
		else dof = color;
		return dof;
	}

	//Includes//
	#ifdef BLACK_OUTLINE
	#include "/lib/outline/outlineOffset.glsl"
	#include "/lib/outline/outlineDepth.glsl"
	#endif


	void main(){
		vec3 color = texture2DLod(colortex0, texCoord, 0.0).rgb;
		float z = texture2D(depthtex1, texCoord.st).x;

		#ifdef BLACK_OUTLINE
			DepthOutline(z);
		#endif

		#if (defined DOF || defined DISTANCE_BLUR)
			color = DepthOfField(color, z);
		#endif

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

#endif

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

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

		gl_Position=ftransform();
	}

#endif