/*//////////////////////////////////////////////////////////////////////////////
//    ##      #####   ######   ######     ##     ####     #######  ##  ##     //
//   ####    ##   ##  # ## #    ##  ##   ####     ##       ##   #  ##  ##     //
//  ##  ##   #          ##      ##  ##  ##  ##    ##       ## #     ####      //
//  ##  ##    #####     ##      #####   ##  ##    ##       ####      ##       //
//  ######        ##    ##      ## ##   ######    ##   #   ## #     ####      //
//  ##  ##   ##   ##    ##      ##  ##  ##  ##    ##  ##   ##   #  ##  ##     //
//  ##  ##    #####    ####    #### ##  ##  ##   #######  #######  ##  ##     //
//----------------------------------------------------------------------------//
//----------------------------------------------------------------------------//
//      #####   ##   ##    ##     #####    #######  ######    #####           //
//     ##   ##  ##   ##   ####     ## ##    ##   #   ##  ##  ##   ##          //
//     #        ##   ##  ##  ##    ##  ##   ## #     ##  ##  #                //
//      #####   #######  ##  ##    ##  ##   ####     #####    #####           //
//          ##  ##   ##  ######    ##  ##   ## #     ## ##        ##          //
//          ##  ##   ##  ######    ##  ##   ## #     ## ##        ##          //
//     ##   ##  ##   ##  ##  ##    ## ##    ##   #   ##  ##  ##   ##          //
//      #####   ##   ##  ##  ##   #####    #######  #### ##   #####           //
/////(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 sampler2D colortex0;

	#ifdef DOF_IS_ON
		uniform float viewWidth, viewHeight, aspectRatio;

		#if AA > 1
			uniform int frameCounter;
			uniform float frameTimeCounter;
			uniform sampler2D noisetex;
		#endif

		#ifdef DISTANCE_BLUR
			uniform ivec2 eyeBrightnessSmooth;
		#endif

		#ifdef DOF
			uniform float centerDepthSmooth;
		#endif

		uniform mat4 gbufferProjection;

		uniform sampler2D depthtex1;

		#ifdef DISTANCE_BLUR
			uniform float rainStrengthS2;
		#endif

	//Optifine Constants//

		const bool colortex0MipmapEnabled = true;

	//Common Functions//

		#if AA > 1
			mat2 Rotate(float angle) {
				return mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
			}
		#endif

		#ifdef DISTANCE_BLUR
			float eBS = eyeBrightnessSmooth.y / 240.0;
		#endif

		float GetCircleDOF(float z1) {
			float DISTANCE_BLUR_STRENGTH = 0.0;
			float DOF_STRENGTH = 0.0;
			float cocDOF = 0.0;
			float cocDIST = 0.0;

			#if defined (NETHER)
				DISTANCE_BLUR_STRENGTH = NETHER_DISTANCE_BLUR_STRENGTH;
				DOF_STRENGTH = NETHER_DOF_STRENGTH;
			#elif defined (OVERWORLD)
				DISTANCE_BLUR_STRENGTH = OVERWORLD_DISTANCE_BLUR_STRENGTH;
				DOF_STRENGTH = OVERWORLD_DOF_STRENGTH;
			#elif defined (END)
				DISTANCE_BLUR_STRENGTH = END_DISTANCE_BLUR_STRENGTH;
				DOF_STRENGTH = END_DOF_STRENGTH;
			#endif

			#if defined (DOF)
				cocDOF = abs(z1 - centerDepthSmooth) * 1.25;
			#endif

			#if defined (DISTANCE_BLUR)
				cocDIST = abs(z1) * 0.001 * DISTANCE_BLUR_STRENGTH * (1.0 + (rainStrengthS2 * eBS * RAIN_BLUR_MULT));
			#endif

			float coc = max(cocDOF, cocDIST);

			float fcoc = coc / (1.0 / DOF_STRENGTH + coc) * gbufferProjection[1][1] * 0.7462686567164179 * 0.05;

			return fcoc;
		}

	//Includes//

		#if AA > 1
			#include "/lib/util/dither.glsl"
		#endif

	//Common Variables//

		const 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 )
		);

	//Common Functions//

		vec3 DepthOfField(vec3 color, float z1) {

			vec3 dof = vec3(0.0);
			vec3 dofSample = vec3(0.0);

			#if AA > 1
				float noise = InterleavedGradientNoise();
				mat2 rotation = Rotate(noise * TAU);
			#endif

			float coc = GetCircleDOF(z1);

			if (coc < 1.0 / max(viewWidth, viewHeight)) return color;

			float hand = float(z1 < 0.56);
			float totalWeight = 0.0;

			float chromaOffset = CHROMA_STRENGTH * 0.25 * coc;

			if (hand < 0.5){

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

					vec2 offset = dofOffsets[i] * coc;

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

						offset /= vec2(aspectRatio, 1.0);

					#if (defined CHROMATIC_ABERRATION && ((defined CHROMATIC_ABERRATION_O && defined OVERWORLD) || (defined CHROMATIC_ABERRATION_N && defined NETHER) || (defined CHROMATIC_ABERRATION_E && defined END)))
						dofSample = vec3(textureLod(colortex0, texCoord + offset + vec2(chromaOffset, 0.0), 0).r,
										 textureLod(colortex0, texCoord + offset, 0).g,
										 textureLod(colortex0, texCoord + offset - vec2(chromaOffset, 0.0), 0).b);
					#else
						dofSample = textureLod(colortex0, texCoord + offset, 0).rgb;
					#endif

					float dofDepth  = texture2D(depthtex1, texCoord + offset).x;
					float dofCoc    = GetCircleDOF(dofDepth);
					float dofWeight = pow(2.0, -distance(coc, dofCoc) * 360.0);
					totalWeight     += dofWeight;
					dofSample       *= dofWeight;

					dof += dofSample;

				}
				dof /= totalWeight;
			} else {

			dof = color;

			}

			return dof;
		}

	//Includes//

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

	//Program//
	#endif

	void main(){
		vec3 color = textureLod(colortex0, texCoord, 0).rgb;
		#ifdef DOF_IS_ON
			float z1   = texture2D(depthtex1, texCoord).x;

			#ifdef BLACK_OUTLINE
				DepthOutline(z1);
			#endif

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

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

#endif

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

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

		gl_Position=ftransform();
	}

#endif