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
OK, I got it, and now I feel kind of stupid 
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:
-
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
-
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