How do I make a shader to cut out different amounts of color?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By MDuck06

I am working on a game centered around color. The BBEG has stolen the color from the world, and you have to beat the different bosses to restore it all. My initial plan was to make a shader that starts out completely grayscale and adds more color to the world whenever you beat a boss, but I can’t get anything to happen other than total grayscale, no grayscale, and burning your retinas from accidentally multiplying all my rgb values.

Please define

cut off

as with rgba values you can use discard.

uniform float step = 0.2;

if color.r > step:
    discard;

Wakatta | 2022-12-16 22:02

By cut out color I mean I want to desaturate (I think that’s the word) the game world by different degrees depending on how many bosses you’ve beaten, so one boss would be barely any color in the world, but still more than the start of the game, and each consecutive boss adds more and more color.
Does that help? Or did I type a paragraph for no reason?

MDuck06 | 2022-12-17 05:11

:bust_in_silhouette: Reply From: Wakatta

Still not entirely sure what you’re aim is but
maybe you could convert rgb to hsv, adjust then convert back to rgb again

uniform vec4 color : hint_color = vec4(1);
uniform float Hue : hint_range(0.0, 1.0, 0.1) = 1;
uniform float Saturation : hint_range(0.0, 1.0, 0.1) = 1;
uniform float Value : hint_range(0.0, 1.0, 0.1) = 1;

vec3 rgb_to_hsv(vec3 c)
{
    vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
    vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));

    float d = q.x - min(q.w, q.y);
    float e = 1.0e-10;
    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}

vec3 hsv_to_rgb(vec3 c)
{
    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

void fragment(){
	vec3 hsv = rgb_to_hsv(color.rgb);
	hsv.x *= Hue;
	hsv.g *= Saturation;
	hsv.z *= Value;

    # for 2d
	COLOR = vec4(hsv_to_rgb(hsv), color.a);

    # for 3d
	ALBEDO = hsv_to_rgb(hsv);
    ALPHA = color.a;
}

You can adjust both the SV values to as you called it “desaturate”

:bust_in_silhouette: Reply From: Gluon

An alternative to Wakatta’s excellent answer might be ColorN (documentation link below).

With this method you should be able to add colours according to your gameplay logic but you would have to work out which ones to use. It can take any of the colours on this doc page as an argument.