+4 votes

Suppose I have a cutout character made of a hierarchy of multiple sprites.
Now I want to turn it into a "ghost" for a while, by modulating its transparency.
The problem is, when I set the transparency of the top-level sprite (the parent of the entire hierarchy), it pretty much works by setting the transparency on all of its subnodes, which looks terrible, because the parts that weren't supposed to be visible (because they were previously obscured by other parts, like clothes, body etc.), now can be seen through other parts :P Here's a simple mockup example that demonstrates this problem:

Bad opacity

What I rather expected is this:

Good opacity
(not made in Godot; I made it in a graphics editing software)

that is, I want the entire image of the sprite to become semi-transparent, not its particular consistuent parts.

If it makes any difference, there may be more than one such a "ghost" on screen, each with different transparency (since some of them will gradually disappear and appear again).

How can this be achieved in Godot?

I tried to save the hierarchy as a scene, then instantiate it and change its opacity instead, but the effect is the same.

asked Nov 26, 2017 in Engine by SasQ (62 points)

Did you find any better solution to this? Is there anything new on Godot 3.1 to achieve it?

2 Answers

+1 vote

I don't know how this can be done easily in Godot, because it relates to how drawing transparent stuff works in OpenGL in the first place.

Taken litterally, it means that all parts of your character must be rendered NOT on screen, but on a temporary buffer at full opacity, and then draw this buffer with transparency (and I bet that's what you did in your image editing software, using 2 layers).

In Godot world, I don't know much ways of doing this.
Maybe you can with a separate viewport, set it to target an offscreen texture, draw your character inside, and render the result on the screen using a single sprite with transparency.

But that's my own theory, it may not be efficient, maybe other people have a better solution.

answered Nov 26, 2017 by Zylann (27,004 points)

Using a light as mask to "cut" the back object can help, but masks may not work fine if you need many (there can be workarounds, though)

Well, I wouldn't expect an effect that is quite common in computer games to be that hard to achieve in as good engine as Godot is :/ So far I've been very satisfied with what I learned about its features.

I thought about the render-to-texture approach too, but I thought that it will be a bad idea, because it would complicate the rendering a lot - I would have to go through that process for every "ghost" I need to draw. So I figured it would not only be a MESS in code, but also might damage the efficiency. (Speaking of which: how many render targets is considered too much? :q ) But I suppose I would need it anyway if I want to apply some other effects (e.g. shaders) to the entire composited hierarchy?

Yes, that's how I made that image. I composited the fully opaque images first into a merged layer, then applied the transparency to the final result. So you're saying that this is the only way to achieve the same effect in Godot? Ech... if only Godot could do that automatically for me for the entire hierarchy by setting some "global transparency" on the top-most node... :/

I'll try the render-to-texture approach for now, maybe it'll do, but I'll wait for some other answers, maybe there's a better solution.

As for using lights for anything not light related: I consider it an ugly hack, and not very reliable either, since the number of light maps applied is limited. I already tried that for another effect I needed (masking the hierarchy to a region), but it didn't work well when the lights started overlapping :P (Maybe I'll ask about that too in a separate question later.)

OK I tried the render target approach:
http://mistu.info/Stuff/Godot/Test_mask.zip
and it seems to work as I expected, but with some minor problems:

  1. Everything I attach as a subnode of the Viewport node disappeared from the scene. The sprites are visible in the ViewportSprite, but I can no longer select any of them in the editor. (I suppose that they're only images in the ViewportSprite, but why did they disappear from the editor? :q )

  2. There's a yellow warning sign next to the ViewportSprite saying that I have to connect it to a viewport set up as "render target" - which is odd, because that's what I did :P It is already connected and it works fine in the editor.

  3. It is quite a mess now, as I suspected. Here's how my test hierarchy looks like now:

    Node2d
      Forest background
        ViewportSprite      # Replaces my hierarchy, I set opacity here.
          AnimationPlayer   # Moves it around and modulates the opacity.
      Viewport
        Sprite1             # This is the root of my original hierarchy.
          Sprite2           # I can't select these anymore, they're gone.
          AnimationPlayer   # Controls the animation of the hierarchy
    

Now it would be great if I could somehow reuse this structure and apply it to other hierarchies I have (perhaps programmatically?). Any ideas?

Unfortunately, this "common" effect is as hard to do in many game engines AFAIK (if you care that much) and as you may have guessed, it always relies on doing two-pass rendering of some sort. If you think there should be a mechanism in Godot to simplify this, perhaps you could ask for a feature on Github, explaining your situation. I've had the same problem with my UI when I wanted it to fade, like you I could see everything through but I didn't bother fixing that...

0 votes

This may be a bit of a dated response but since it came up on Google I'll bite:

Put all of those sprites onto a new Node2D then set the new Node2D's self_modulate.a to whatever the transparency you want to be.

It will, much like the other posters suggest, render all the children of that Node2D as opaque, then change just the opacity of the final result (the Node2D's self_modulate).

I don't know exactly when selfmodulate was introduced, but the mechanism of changing opacity via a [self]modulate.a property was new to 3.0.

answered Sep 7, 2018 by Hammer Bro. (93 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.