godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
86.62k stars 19.31k forks source link

Changing between scenes with global Volumetric Fog, VoxelGI weird behavior #85642

Open Defwentz opened 7 months ago

Defwentz commented 7 months ago

Godot version

4.2.stable [46dc27791]

System information

Windows 10 - Godot v4.2.stable - Vulkan (Forward+)

Issue description

I have a 3D scene with VoxelGI lighting and global Volumetric Fog enabled. It looks as expected with F6 running current scene. But when I use change_scene_to_file() or change_scene_to_packed() the change to the this scene, it's very white and foggy. This can make the editor looks the same as well but I can't reliably trigger it. Not 100% sure, but I think I was able to reliably get rid of the editor fog by disable/enable global volumetric fog.

屏幕截图(467) 屏幕截图(468)

I have a workaround to disable global volumetric fog by default then re-enable it after a short timer on scene _ready.

Steps to reproduce

In the minimal reproduction project, with start scene(start.tscn) and target scene(light.tscn). start has global volumetric fog, target has voxel and volumetric fog.

  1. Run target scene to see the red emissive light.
  2. Run start scene then click change scene at bottom light left, to see target scene has become white and foggy.

Minimal reproduction project

voxelgi_volfog_bug.zip

Rytelier commented 7 months ago

Same happened in my project, it doesn't even need to change scene in a script, it will happen just when loading scene with camera facing away from voxelGI volume.

bitsawer commented 7 months ago

Generally the scene change API just shuffles nodes around and it's nothing you can't do yourself, so for example updating Environment effects, SDFGI or VoxelGI should often be done manually if the scene geometry or node structure changes enough. Many do this by for example disabling WorldEnviroment for a frame so that all relevant effect data will be re-created and updated. In the demo, you can do this by for example adding this to frame_look_camera.gd:

func _ready():
    var world = get_node("../WorldEnvironment") as WorldEnvironment

    var env = world.environment
    world.environment = null
    await RenderingServer.frame_post_draw
    world.environment = env

Usually any visual flashing etc. during these "resets" can be masked with a loading screen, fades etc. Usually only the programmer (you) knows what and how much must be reset when chaning the node tree, so if Godot tries to guess this it can result in some inefficient or redundant updates.

Defwentz commented 7 months ago

Thanks! this is good to know, I can finally stop using the timer. Btw, I tested the camera facing away from VoxelGI, it's true and reset on ready doesn't fix it. I guess the intended usage is camera must be within the VoxelGI field and no more than one VoxelGI, because I tried to have another VoxelGI node and they overwrite each other depending who the camera see first despite using 2 set of data.

bitsawer commented 7 months ago

I'm not sure exactly what the VoxelGI and camera facing away issue is and how it manifests (I guess it's kind of hard to describe it using only text), but it might be worth making a separate bug report for it with a test project (if you can't find an existing bug report for that issue).

Also, technically there can be at max 8 VoxelGI nodes at the same time, but one object can only be influenced by two at the same time: https://github.com/godotengine/godot/issues/80361#issuecomment-1667292158