Parametric Linear RGB Dimmer

This shader allows for parametric dimming of individual RGB channels, providing control over the intensity of red, green, and blue values. The effect can be restricted to specific regions of the element using a height-based parameter, allowing for dynamic on/off transitions. This shader has a parameter to apply only to visible areas as well, making it perfect for overlays

Originally designed to simulate a “missing HP” effect for character portraits, inspired by classic cRPGs like Baldur’s Gate 1 & 2, the shader visually represents depleted health in a clear and striking manner.

Additional features, such as rotation and region-reversal options, were added to increase versatility, making the shader adaptable to a wide variety of use cases, including diagonal and horizontal effects.

Shader code
shader_type canvas_item;

// Parameters to control the damping factors for red, green, and blue channels
uniform float red_factor : hint_range(0.0, 1.0) = 1.0;
uniform float green_factor : hint_range(0.0, 1.0) = 1.0;
uniform float blue_factor : hint_range(0.0, 1.0) = 1.0;

// Parameter to control the alpha factor
uniform float alpha_factor : hint_range(0.0, 1.0) = 1.0;

// Parameter to control the height percentage of the shader effect
uniform float height_percent : hint_range(0.0, 100.0) = 50.0;

// Boolean to reverse the order of height influence
uniform bool reverse_order = false;

// Boolean to apply rotation to the height parameter
uniform bool apply_rotation = false;

// Boolean to affect only visible (fully opaque) pixels
uniform bool affect_only_visible = false;

// Rotation angle in radians (applied if apply_rotation is true)
uniform float rotation_angle : hint_range(0.0, 6.28319) = 0.0; // 0 to 2*PI

void fragment() {
    // If `affect_only_visible` is true and alpha is less than 1, do nothing.
    if (affect_only_visible && COLOR.a < 1.0) {
        // COLOR remains unchanged.
    } else {
        // Calculate the UV based on the local space of the element
        vec2 uv = UV;

        // Apply rotation if the flag is enabled
        if (apply_rotation) {
            float cos_angle = cos(rotation_angle);
            float sin_angle = sin(rotation_angle);
            uv = vec2(
                uv.x * cos_angle - uv.y * sin_angle,
                uv.x * sin_angle + uv.y * cos_angle
            );
        }

        float relative_height = uv.y;

        // Convert height_percent to a normalized value (0.0 to 1.0)
        float height_threshold = height_percent / 100.0;

        // Reverse the order if the reverse_order flag is set
        if (reverse_order) {
            relative_height = 1.0 - relative_height;
        }

        // Apply the shader only if the fragment is within the specified height range
        if (relative_height <= height_threshold) {
            // Reduce the red, green, and blue channels by their respective factors
            COLOR.rgb = vec3(COLOR.r * red_factor, COLOR.g * green_factor, COLOR.b * blue_factor);
            // Adjust the alpha channel
            COLOR.a *= alpha_factor;
        } else {
            // Keep the original color below the height threshold
            COLOR = texture(TEXTURE, UV);
        }
    }
}
Tags
alpha, dimmer, godot4, hp, linear, parametric, portrait, progress bar, rgb
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

Samuel Wolffang based rgb shift shader

rgb offset shader v2

Moving RGB Rainbow Stripes

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments