 #define TONEMAPPER_ACES 3
 
 vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always outputs clamped [0;1] color
-
+	// Ensure color values passed to tonemappers are positive.
+	// They can be negative in the case of negative lights, which leads to undesired behavior.
 	if (params.tonemapper == TONEMAPPER_LINEAR) {
 		return color;
 	} else if (params.tonemapper == TONEMAPPER_REINHARD) {
-		return tonemap_reinhard(color, white);
+		return tonemap_reinhard(max(vec3(0.0f), color), white);
 	} else if (params.tonemapper == TONEMAPPER_FILMIC) {
-		return tonemap_filmic(color, white);
+		return tonemap_filmic(max(vec3(0.0f), color), white);
 	} else { // TONEMAPPER_ACES
-		return tonemap_aces(color, white);
+		return tonemap_aces(max(vec3(0.0f), color), white);
 	}
 }
 

	return color_tonemapped / white_tonemapped;
}

vec3 tonemap_aces(vec3 color, float white) {
	const float exposure_bias = 0.85f;
	const float A = 2.51f * exposure_bias * exposure_bias;
	const float B = 0.03f * exposure_bias;
	const float C = 2.43f * exposure_bias * exposure_bias;
	const float D = 0.59f * exposure_bias;
	const float E = 0.14f;

	vec3 color_tonemapped = (color * (A * color + B)) / (color * (C * color + D) + E);
	float white_tonemapped = (white * (A * white + B)) / (white * (C * white + D) + E);

	return color_tonemapped / white_tonemapped;
}

		color += screen_space_dither(gl_FragCoord.xy);
	}

	color = apply_tonemapping(color, params.white);

	color = linear_to_srgb(color); // regular linear -> SRGB conversion

