Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preprocess on GPU Particles not working correctly after await #75723

Open
uheartbeast opened this issue Apr 5, 2023 · 8 comments · May be fixed by #78671
Open

Preprocess on GPU Particles not working correctly after await #75723

uheartbeast opened this issue Apr 5, 2023 · 8 comments · May be fixed by #78671

Comments

@uheartbeast
Copy link

Godot version

4.0.2.stable

System information

Windows 11

Issue description

If you await and then switch to a scene with GPU particles that are supposed to preprocess, they don't preprocess correctly.

Steps to reproduce

  1. Create a scene that has GPU particles that preprocess (larger preprocess times make this more obvious).
  2. Use a box shape for emissions
  3. Create another scene that awaits for 1 second, and then changes to the particle scene

Minimal reproduction project

I've included a minimum example of the issue. Simply run the game and you'll see that the preprocess for the particles doesn't work correctly.

PreprocessBugMin.zip

@Calinou
Copy link
Member

Calinou commented Apr 5, 2023

Can you reproduce this with CPUParticles?

@uheartbeast
Copy link
Author

uheartbeast commented Apr 5, 2023

Can you reproduce this with CPUParticles?

No. CPUParticles work correctly.

I mentioned this in the example project, but I forgot to put it in this issue report.

@SoulForMachine
Copy link
Contributor

SoulForMachine commented May 20, 2023

The issue seems to be that the GPUParticles are preprocessed without applying the world transform. When I add a camera to the particle scene, I see this (the sprite is at the scene origin):

image

So all the particles are preprocessed, just at the wrong place (in the original scene the left half of them off the screen). On the left you can see the preprocessed particles centered around the origin, and on the right you can see the new particles appearing after the scene starts, centered around the correct particle system world position (I offset it by 128px, the with of the emitter box).

I'll take this on and fix it.

@SoulForMachine
Copy link
Contributor

SoulForMachine commented Jun 25, 2023

Here is what happens:

  • starting_scene.gd _ready() without await:

    • [frame 1] MessageQueue::get_singleton()->flush() in SceneTree::physics_process() calls CanvasItem::_notification() with NOTIFICATION_ENTER_TREE for GPUParticles2D and adds itself to SceneTree::xform_change_list
    • [frame 1] xform first updated by second flush_transform_notifications() in SceneTree::physics_process() with position 128
    • [frame 1] particles preprocessing done from RenderingServerDefault::draw()
  • starting_scene.gd _ready() with await:

    • first 47 frames no xform notifications to flush in SceneTree::physics_process()
    • [frame 48] SceneTree::process -> process_timers -> instantiate GPUParticles2D
    • [frame 48] message_queue->flush() in Main::iteration() calls CanvasItem::_notification() with NOTIFICATION_ENTER_TREE for GPUParticles2D and adds itself to SceneTree::xform_change_list
    • [frame 48] particles preprocessing done from RenderingServerDefault::draw() with position 0
    • [frame 49] xform first updated by first flush_transform_notifications() in SceneTree::physics_process() with position 128

When the particles scene is created after the timer is triggered, the GPUParticles2D is created and added to the update list, but SceneTree::flush_transform_notifications() isn't called before drawing it, so preprocessing which happens on the first draw uses initial position (0, 0).

To fix this, we need to call MessageQueue::get_singleton()->flush() in SceneTree::process(), after timers have been processed and before flush_transform_notifications() - in the same way as it is already called in other 2 places in the same function, with a comment "small little hack". This will put the GPUParticles2D into the xform_change_list before the call to xform flush.

image

Maybe message queue flush in SceneTree::physics_process also needs to go after the timers and tweens have been processed?

In any case all these "small little hacks" will have to be refactored at some point. :)

@SoulForMachine
Copy link
Contributor

Created pull request #78671

@SoulForMachine SoulForMachine linked a pull request Jun 25, 2023 that will close this issue
@crayonape
Copy link

Is this fixed? Because I met this problem in Godot v4.1.1

@Calinou
Copy link
Member

Calinou commented Oct 11, 2023

Is this fixed? Because I met this problem in Godot v4.1.1

This isn't fixed yet, as #78671 isn't merged yet (see review comments as for why it probably won't be accepted in its current state).

@crayonape
Copy link

Is this fixed? Because I met this problem in Godot v4.1.1

This isn't fixed yet, as #78671 isn't merged yet (see review comments as for why it probably won't be accepted in its current state).

is this fixed in Godot v4.2?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants