3D healthbar shader - issue with setting COLOR (SOLVED)

Godot Version

4.2.2

Question

I’m trying to use this simple healthbar shader from Godot Shaders on a MeshInstance material:

shader_type canvas_item;

uniform vec4 color : source_color = vec4(vec3(1.0), 1.0);
uniform float health : hint_range(0.0, 1.0) = 0.5;

void fragment() {
    vec4 background_color = vec4(color.rgb * vec3(0.5), color.a);
    COLOR = UV.x < health ? color : background_color;
}

Godot complains about COLOR, saying “Constants cannot be modified”.

After some searching, I then learned that you need to set COLOR in Vertex and read the value again in Fragment.

Now I’m very inexperienced with shaders, how could I make this work?

You should use shader_type spatial; on a MeshInstance3D material. Then, you assign the color to ALBEDO and ALPHA, not COLOR.

Thanks, that got me a step further. However, it does not seem that the formula that’s calculating the color on ALBEDO is valid.

Godot complains about “Invalid ternary operator: bool, vec4, vec3”.

shader_type spatial;

uniform vec4 color : source_color = vec4(vec3(1.0), 1.0);
uniform float health : hint_range(0.0, 1.0) = 0.5;
uniform vec4 new_color : source_color = vec4(vec3(1.0), 1.0);

void fragment() {
	vec3 background_color = vec3(color.rgb * vec3(0.5));
	ALBEDO = UV.x < health ? color : background_color;
}

Just use color.rgb instead of color. ALBEDO is vec3. If you need the alpha channel, you can add ALPHA = color.a to the end. But I can see it’s always 1.0, so the ALPHA assignment can be omitted.

1 Like

I got it, thanks a lot!

Here’s the end result for anyone who might need this in the future:

(I also added an optional billboard mode which will work on QuadMesh.)

shader_type spatial;
render_mode unshaded;

uniform bool use_billboard;
uniform vec4 color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform vec4 background_color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform float health : hint_range(0.0, 1.0) = 0.5;

void vertex() {
	if (use_billboard){
        MODELVIEW_MATRIX = VIEW_MATRIX * mat4(INV_VIEW_MATRIX[0], INV_VIEW_MATRIX[1], INV_VIEW_MATRIX[2], MODEL_MATRIX[3]);
	}
}

void fragment() {
	ALBEDO = UV.x < health ? color.rgb : background_color.rgb;
	ALPHA = UV.x < health ? color.a : background_color.a;
}

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.