Godot Version
4.4.1 stable
The Goal
I have a straightforward scene-switching node that I’m working on.
I want to crossfade from old scenes to new ones, with a nice shader-driven animation. Here’s the important part:
## GO TO SCENE
func go_to_scene(new_scene: Node, _shader: String = "default"):
start_crossfade()
for child in world.get_children():
child.reparent(sub_viewport) # <- the part that Godot doesn't like
if current_scene:
prior_scene = current_scene
current_scene = null
current_scene = new_scene
func start_crossfade(new_duration: float = 2.0):
crossfade_max_duration = new_duration
crossfade_duration = crossfade_max_duration
crossfade_rect.material.set_shader_parameter("completion", 1.0)
#crossfade_rect.visible = true # <- I know this is commented, more on this below.
state = states.CROSSFADING
The “old” children of WorldManager
are being stored as sub-children of the SubViewport
. As I understand it, this should cause them to be rendered by the SubCamera
right away.
Then, I show my CrossfadeRect
, which views the SubViewport
’s output texture, and a shader makes the CrossfadeRect
transparent in a pattern using a shader.
This should result in a nice crossfade from my old scene to my new one, without having to snapshot or pause–I would like water to keep flowing, flags to continue waving, and so on in the old scene, hence this reparenting strategy.
But, seemingly, the SubCamera
doesn’t immediately render its newly-assigned children.
The Issue
Right now, the result of this is a brief “blink” back to the previous scene, every time I switch scenes, as seen here:
This happens if I uncomment crossfade_rect.visible = true
in the above code sample, too. What happens then is that I get the same blinking frame, but the output is pure grey.
The Question
How am I supposed to be doing this cross-fade? As far as I understand, this SubViewport
trick is the easiest way to press a group of Node2Ds
into one shader-readable texture.
I could defer the reparenting, but I feel like that just results in blinking on a different frame instead.
I could try duplicating my Nodes to the SubViewport
, letting the crossfade start, and then freeing the originals after, but that seems like such a boneheaded hack for something that should be simple to fix.