float smartUpscaleLuma(vec3 color) {
	return dot(color, vec3(0.2126, 0.7152, 0.0722));
}

void sharpenFilter(inout vec3 color, in vec2 coord) {
#if SMART_UPSCALING > 0
	vec2 pixel = 1.0 / vec2(viewWidth, viewHeight);
	vec3 north = texture2D(colortex1, coord + vec2(0.0,  pixel.y)).rgb;
	vec3 south = texture2D(colortex1, coord + vec2(0.0, -pixel.y)).rgb;
	vec3 east  = texture2D(colortex1, coord + vec2( pixel.x, 0.0)).rgb;
	vec3 west  = texture2D(colortex1, coord + vec2(-pixel.x, 0.0)).rgb;
	vec3 average = (north + south + east + west) * 0.25;

	#if SMART_UPSCALING == 1
		const float presetStrength = 0.14; // Ultra Quality / external scale: 90%
	#elif SMART_UPSCALING == 2
		const float presetStrength = 0.24; // Quality / external scale: 83%
	#elif SMART_UPSCALING == 3
		const float presetStrength = 0.38; // Balanced / external scale: 75%
	#elif SMART_UPSCALING == 4
		const float presetStrength = 0.54; // Performance / external scale: 67%
	#else
		const float presetStrength = 0.72; // Ultra Performance / external scale: 50%
	#endif

	float edge = abs(smartUpscaleLuma(color) - smartUpscaleLuma(average));
	float edgeProtection = 1.0 - smoothstep(0.06, 0.34, edge) * 0.58;
	float scaleDeficit = clamp(1.0 - float(RENDER_SCALE) * 0.01, 0.0, 0.5);
	float calibratedStrength = presetStrength * mix(0.72, 1.0, scaleDeficit * 2.0);
	vec3 reconstructed = color + (color - average) * calibratedStrength * SHARPENING * edgeProtection;

	#ifdef EDGE_RECONSTRUCTION
		vec3 neighborhoodMin = min(color, min(min(north, south), min(east, west)));
		vec3 neighborhoodMax = max(color, max(max(north, south), max(east, west)));
		vec3 tolerance = vec3(0.012 + scaleDeficit * 0.018);
		color = clamp(reconstructed, neighborhoodMin - tolerance, neighborhoodMax + tolerance);
	#else
		color = reconstructed;
	#endif
#endif
	#if SOLAS_BY_SEPTONIOUS != 1
		color = vec3(0.0);
	#endif
}
