Search code examples
colorsspritegodotgdscript

How to change the saturation and overlay of a sprite in Godot


I have been planning to change my sprite to a bit darker color through changing saturation and hue values. But it seems very tricky to do so as the Godot modules only talk about changing the color of a sprite though the modulate option like this:

node.modulate= Color(0, 50, 2,0.5)

Doing so is changing the entire sprite to a new color whereas I just want to make the existing colors to a bit darker color the way we do in Photoshop using "Curves" or "Levels" - but not as refined. Any rudimentary method would also help.

Currently, I can only do "Color Overlay" without changing the opacity. Any method of adding a color overlay with opacity change would be helpful as long as it doesn't change the opacity of the entire sprite but just the overlay color.

I am working on a 2D game with imported PNG Sprites. If any more information is required, I'll be happy to provide it.

Additional Information -

What my sprite looks like

enter image description here

I want to make it darker through code twice like this -

enter image description here enter image description here

By doing node.modulate= Color(0.0, 0.0, 0.0,1) it becomes like this - enter image description here

The reason why I'm avoiding to do this manually because I have too many sprites and doing this for all of them will be tedious.


Solution

  • Example color difference image

    Here's two examples of how you can darken a sprite via code.

    The first method is by using self_modulate. Modulation is calculated by multiplying the modulation value by texture color value. This shows that modulation of (1, 1, 1, 1) is the same as the original texture. A modulation of (0.5, 0.5, 0.5, 1) halves the texture color making it darker like it has a half opacity black overlay.

    # On a node that extends CanvasItem
    self_modulate = Color(0.5, 0.5, 0.5, 1.0)
    

    The second method is to subtract the texture value by a constant. This creates a texture that's more saturated but darker.

    The shader code:

    shader_type canvas_item;
    
    uniform float difference: hint_range(0.0, 1.0) = 0.0;
    
    void fragment() {
        vec4 tex = texture(TEXTURE, UV);
        COLOR.rgb = tex.rgb - vec3(difference);
        COLOR.a = tex.a;
    }
    

    The other code:

    # On a node that extends CanvasItem
    material.set_shader_param('difference', 0.3)
    

    These effects can be combined to produce the desired result. Play around with the shader to produce a better result.

    Hope this helps.