Efficient way to selectively gray-out/color specific objects in a 3D environment?

Godot Version

Godot 4.3

Question

I’ve been trying to find a way to create a selective grayscale effect where some selected objects are rendered in color and the rest are grayed out, something like the attached image. The selected object(s) will not necessarily be of a specific homogeneous color. Also, it’s important to be able to dynamically switch between objects.
Things that I’ve already tried:

  • Screen space shader (applied on a CanvasItem overlay) but there is no way to tell the shader to exclude specific objects, as far as I know.
  • Adding a second pass shader material to each object that greys it out. This kind-of worked but I ran into problems with my post-processing shader which rendered the objects in color anyway. I’m also using GridMaps which makes it impossible to apply shader materials to the individual tiles in a way that they’re dynamically switchable.
  • Splitting objects between different viewports/cameras. This also kind-of worked but it would mean I’d have to restructure my whole project to use multiple cameras/effects just to achieve this visual effect. Also, shuffling objects dynamically between viewports becomes a bit hard to keep track of.

Anything I’m missing?

Godot 4.3 adds a new CompositorEffects

Have you looked into? The terminology suggests you can place effects at different moments in the pipeline. I haven’t looked into so i don’t know if it’s a dead end.

Thanks for pointing this out. My shader-fu is not that good so I’ll have to read through it in detail. From a first scroll however, what I understand is that it allows you to inject shader code during the rendering. It’s still a bit unclear how you could use this to implement compositor effects on a by-object basis.

There is a video attached from one of the Godot devs that goes through an example.

My thought would be to do the grayscale everything early on then allow for a single shader to color the your focused object.

Although this assumption is that individual materials happen later in the process, but that doesn’t seem likely.

My second thought is to somehow create a mask that covers your focus object. Then when you go to grayscale everything except the masked area. I think this could be more feasible but the question is how do you generate a mask that will be used later… Idk i also don’t have good shader skills.

Yes that might be possible. I’ll have to look into it. I’m just somewhat surprised that I couldn’t find anyone who has tried it before. Not even in other engines, just to try and figure out how they implemented it.