My shader doesn't want to update (C#)

Godot Version

4.5.1

Question

Hello folks

I want to put something in greyscale in my game when certains conditions are met (for instance, after a unit moved in a tactical rpg), and I created a shader for that. Here’s the script :

shader_type canvas_item;

/**
*	If true, the target will become greyscaled
*/
uniform bool greyed = false;

void fragment() {
	// Called for every pixel the material is visible on.
	vec4 original_color = texture(TEXTURE, UV);
	if(greyed){ // Becomes grayscaled only when asked
		float grayscale = (original_color.r + original_color.g + original_color.b)/3.0f;
		vec3 grayscale_color = vec3(grayscale,grayscale,grayscale);
		COLOR.rgb = grayscale_color;
		COLOR.a = original_color.a;
	}

}

However, when the following code is executed :

    public void HasPlayed()
    {
        Active = false;
        GD.Print("It should be greyed");
        ((ShaderMaterial)Material).SetShaderParameter("greyed",true);
        GD.Print(((ShaderMaterial)Material).ResourceName);
        GD.Print(((ShaderMaterial)Material).GetShaderParameter("greyed"));
    }

I have the things printed, and even a “true” in the last line, but it’s still colorful, despite the object loading the shader in the engine

(CanvasItem of the object I want to greyscale)

I’m new on shaders, so I’m probably doing something wrong, but I don’t know what

Thank you in advance

Is your shader assigned to the BandW material? Can you see greyed in the Shader Parameters section in the Inspector?

1 Like

I am not sure to be fully honest. My GD.Print(((ShaderMaterial)Material).ResourceName);returns a blank line, so maybe I didn’t fully assigned it, or something ? I don’t know, I’m really new to this

I see it, in editor and in runtime, except that it’s names Greyed, despite not being capitalized in the shader code. It has the docstring I written tho

ETA : I tried putting “Greyed” instead of “greyed” in my code, and it doesn’t work either. I also change GD.Print(((ShaderMaterial)Material).ResourceName);into GD.Print(((ShaderMaterial)Material).ResourcePath);and it returns the ShaderMaterial path

Click on BandW.tres (in your screenshot) to expand it. There should be a property Shader containing your shader file. If it’s empty, the shader isn’t assigned to the material.

1 Like

It seems to be loaded

OK, I got it, and now I feel kind of stupid :sweat_smile:

I used my shader on a scene Unit, that inherits from a CharacterBody2D. However, it didn’t applied on its Sprite2D

I now have another problem tho : When I make greyed true, everyone turn grey

Before

After I moved one guy

And I only want the one that moved to become grey

Both the material and the shader have to be “local to scene”, I think.

2 Likes

The shader doesn’t have to be.

2 Likes

Thank you for your answers, and sorry for the late reply (asking on New Year’s Eve wasn’t the best idea I had, but nonetheless, happy new years)

I will compile every answers I had here, for those who come after and have the same issue:

  1. Make sure that the Texture (for instance, the sprite) has the shader, either by directly giving it, ir making it inherits from its parents node, as they are the thing you view

  2. Use “Local to scene” for the ShaderMaterial, so that each instance have its own copy of ShaderMaterial, compared to unchecked “Local to scene”, where they all share the same instance

Thank you very much to all of you !

1 Like