/*
Complementary Shaders by EminGT, based on BSL Shaders by Capt Tatsu
*/

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

ivec2 neighbourhoodOffsets[8] = ivec2[8](
	ivec2(-1, -1),
	ivec2( 0, -1),
	ivec2( 1, -1),
	ivec2(-1,  0),
	ivec2( 1,  0),
	ivec2(-1,  1),
	ivec2( 0,  1),
	ivec2( 1,  1)
);

void NeighbourhoodClamping(vec3 color, inout vec3 tempColor, float depth, inout float edge) {
	vec3 minclr = color, maxclr = color;

	ivec2 texelCoord = ivec2(gl_FragCoord.xy);

	for (int i = 0; i < 8; i++) {
		float depthCheck = texelFetch(depthtex1, texelCoord + neighbourhoodOffsets[i], 0).r;
		if (abs(GetLinearDepth(depthCheck) - GetLinearDepth(depth)) > 0.09) edge = 25.0;
		vec3 clr = texelFetch(colortex1, texelCoord + neighbourhoodOffsets[i], 0).rgb;
		minclr = min(minclr, clr); maxclr = max(maxclr, clr);
	}

	tempColor = clamp(tempColor, minclr, maxclr);
}

void TAA(inout vec3 color, inout vec4 temp) {
	float depth = texture2D(depthtex1, texCoord).r;
	float noTAA = texture2D(colortex7, texCoord).r;
	if (depth < 0.56 || noTAA > 0.5) { // Fixes entities and hand
		return;
	}

	vec3 coord = vec3(texCoord, depth);
	vec3 cameraOffset = cameraPosition - previousCameraPosition;
	vec2 prvCoord = Reprojection(coord, cameraOffset);
	
	vec2 view = vec2(viewWidth, viewHeight);
	vec3 tempColor = texture2D(colortex2, prvCoord).gba;
	if (tempColor == vec3(0.0)) { // Fixes the first frame
		temp = vec4(temp.r, color);
		return;
	}

	float edge = 0.0;
	NeighbourhoodClamping(color, tempColor, depth, edge);
	
	vec2 velocity = (texCoord - prvCoord.xy) * view;

	float blendFactor = float(prvCoord.x > 0.0 && prvCoord.x < 1.0 &&
	                          prvCoord.y > 0.0 && prvCoord.y < 1.0);

	// The original filter kept at least 65% of the previous frame while the
	// camera was moving.  That hides aliasing, but smears block textures.  Give
	// stable pixels enough history to settle and quickly favour the current
	// frame as soon as screen-space motion or a colour discontinuity appears.
	float pixelVelocity = length(velocity);
	float motionConfidence = exp(-pixelVelocity * TAA_MOTION_RESPONSE);
	float colorDelta = length(color - tempColor)
				   / (0.25 + max(length(color), length(tempColor)));
	float historyRejection = clamp(colorDelta * TAA_COLOR_REJECTION, 0.0, 1.0);

	#if AA == 4
		float stableHistory = min(TAA_STATIC_HISTORY + 0.10, 0.90);
		float movingHistory = min(TAA_MOVING_HISTORY + 0.04, 0.35);
	#else
		float stableHistory = TAA_STATIC_HISTORY;
		float movingHistory = TAA_MOVING_HISTORY;
	#endif

	float historyWeight = mix(movingHistory, stableHistory, motionConfidence);
	historyWeight *= 1.0 - TAA_REJECTION_STRENGTH * historyRejection;
	historyWeight = clamp(historyWeight, 0.04, stableHistory);
	historyWeight *= exp(-length(cameraOffset) * edge);
	blendFactor *= historyWeight;
	
	color = mix(color, tempColor, blendFactor);
	temp = vec4(temp.r, color);
	//if (edge > 0.05) color.rgb = vec3(1.0, 0.0, 1.0);
}
