Screen HSL Adjustment

Adjust the colors of the screen behind the ColorRect (or other CanvasItem node) used to hold this shader using HSL by changing ONLY the color property of the ColorRect node.  Also works with Modulate.

Hue is additive via the red channel.  Saturation, luminosity, and alpha are multiplicitive via the green, blue, and alpha channels, respectively.

I made this so that you can more easily manipulate the colors of the screen.  For instance, it’s compatible with tweens.

For instance, to desaturate the screen over 3 seconds in GDScript:

get_tree().create_tween().tween_property($YourColorRect, "color", Color(0.0, 0.0, 1.0), 3.0)

Or, to double the luminosity while shifting the hue by 180 degrees over 5 seconds in C#:

GetTree().CreateTween().TweenProperty(GetNode("YourColorRect"), "color", new Color(0.5f, 1f, 2f), 5f);

To set it up, make a ColorRect node in front of your screen.  Add the shader to the materials.  You use (HDR) values as inputs in the color (or modulate) property of the node to adjust the colors of the screen behind the node.

Shader code
// By Amy Gilhespy.
// I hereby dedicate this shader to the public domain.
// https://creativecommons.org/publicdomain/zero/1.0/


shader_type canvas_item;

uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;

vec3 hsl2rgb(vec3 hsl)
{
	float l = clamp(hsl.z, 0.0, 1.0);
    vec3 rgb = clamp(abs(mod(fract(hsl.x) * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);
    return l + clamp(hsl.y, 0.0, 1.0) * (rgb - 0.5) * (1.0 - abs(2.0 * l - 1.0));
}

vec3 rgb2hsl(in vec3 rgb)
{
	float h = 0.0;
	float s = 0.0;
	float l = 0.0;
	float r = rgb.r;
	float g = rgb.g;
	float b = rgb.b;
	float cMin = min(r, min(g, b));
	float cMax = max(r, max(g, b));
	l = (cMax + cMin) * 0.5;
	if (cMax > cMin) {
		float cDelta = cMax - cMin;
		float invCDelta = 1.0 / cDelta;
		s = l < 0.5 ? cDelta / (cMax + cMin) : cDelta / (2.0 - (cMax + cMin));
		if (r == cMax) {
			h = (g - b) * invCDelta;
		} else if (g == cMax) {
			h = 2.0 + (b - r) * invCDelta;
		} else {
			h = 4.0 + (r - g) * invCDelta;
		}
		if ( h < 0.0) {
			h += 6.0;
		}
		h = h * (1.0 / 6.0);
	}
	return vec3(h, s, l);
}

void fragment() {
	// Get the color behind the ColorRect (or whatever CanvasItem you use):
	vec4 source = texture(SCREEN_TEXTURE, SCREEN_UV);

	// Get the color chosen in the ColorRect (also works with Modulate, textures, etc):
	vec4 shift = vec4(COLOR.rgb / texture(TEXTURE, UV).rgb, COLOR.a);

	// Convert and shift the color as HSL (Hue is added, Sat/Lum are multiplied):
	vec3 rgb = hsl2rgb(rgb2hsl(source.rgb) * vec3(1.0, shift.gb) + vec3(shift.r, 0.0, 0.0));
	
	float alpha = source.a * shift.a;
	COLOR = vec4(rgb, alpha);
}
Live Preview
Tags
adjust, adjustment, hsl, modulate, tint
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

Related shaders

Depth adjustment for Clipping protection

2D Controlled Shine Highlight With Angle Adjustment

Pixelate Screen Effect

guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments