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

[3.x] Physics Interpolation: Add support for CPUParticles2D #80176

Merged
merged 1 commit into from
Aug 8, 2023

Conversation

lawnjelly
Copy link
Member

@lawnjelly lawnjelly commented Aug 2, 2023

Similar to the existing 3D CPUParticles physics interpolation.

Explanation

As with 3D, this works by placing the global coordinate particles in actual global space, unlike the original implementation which has global particles in local space. i.e. The legacy implementation compensates for the transform introduced by the parent node by multiplying the inverse with each particle transform.

The legacy implementation is somewhat strange, but works before physics interpolation. Unfortunately with interpolation, the maths doesn't work well doing this approach, it is easier to store each particle in global space and use an identity transform (or rather camera transform in the case of 2D) for the node.

UPDATE:
reduz has confirmed that the legacy implementation worked that way just to fit into the existing framework (which didn't support ignoring parent xform).
Now that this PR has added the framework to support this, we can probably go ahead and switch the legacy non-interpolated particles to also use global space (this can be done by flipping the #define GODOT_CPU_PARTICLES_2D_LEGACY_COMPATIBILITY). But I will leave that to a later PR and beta, just in case it caused any regressions with the non-interpolated particles.

Notes

  • Adding this as draft to get some quick testing by enthusiasts, now that basic 2D interpolation is merged and we are hoping to have a beta soon.
  • For compatibility, there is a compile time define (GODOT_CPU_PARTICLES_2D_LEGACY_COMPATIBILITY) to leave the non-interpolated global particles in "pseudo globalspace" (i.e. the same as before), which is currently set.
    This is safer as far as regressions (especially y-sort and custom shaders), but slightly less efficient (because it does an extra transform per particle). Beta testing with the physics interpolated version should let us know whether it would be safe to try disabling this define.
  • The primary reason for the set_canvas_item_use_identity_transform() functionality (rather than setting as top level) is that setting as top level breaks y-sort. The reason for this is that set as top level sets the item parent to be the viewport rather than the actual parent. This is something that was reported in my smoothing addon. Whereas when attached to the regular parent in the VisualServer, we have the option to fix y-sort for global particles.
  • There is as yet no support for "streaking", which is an advanced feature of 3D particle physics interpolation which allows particles to be emitted between physics ticks. This can be added at a later stage.
  • Y-sort still seems to work fine with the interpolated particles.

Special Note

As the particle system calculations are made on physics ticks, the "fidelity" of the simulation depends on the tick rate. While physics interpolation is quite usable down to e.g. 10tps, particles in particular may start to look ropey at very low tick rates, so 20-30tps minimum is probably more recommended when using particles.
When implemented, "streaking" will help to compensate for low tick rates (as with 3D), however, there are still lower limits due to the discrete nature of the simulation.

The same analogous drop in fidelity occurs typically in physics at low tick rates, where tunnelling etc becomes a problem.

(In the past, I've programmed more advanced stepping strategies in more game-specific engines, like having 2x base, 3x base multipliers for the base tick rate, so different systems can be updated at different tick rates. But that is well out of scope here for Godot.)

@lawnjelly lawnjelly added this to the 3.6 milestone Aug 2, 2023
@lawnjelly lawnjelly changed the title Physics Interpolation - add support for CPUParticles2D [3.x] Physics Interpolation - add support for CPUParticles2D Aug 2, 2023
@@ -667,6 +679,8 @@ void VisualServerCanvas::render_canvas(Canvas *p_canvas, const Transform2D &p_tr
memset(z_list, 0, z_range * sizeof(RasterizerCanvas::Item *));
memset(z_last_list, 0, z_range * sizeof(RasterizerCanvas::Item *));

_current_camera_transform = p_transform;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

This is to avoid passing the camera transform down the rendering function calls, as it won't be used in 99% of cases, because the camera transform is normally concatenated with the item global transform. It should be invariant throughout the call (I hope 😉 ). If this assumption proves incorrect we can pass it down or take different approach.

@lawnjelly lawnjelly force-pushed the fti_2d_particles branch 4 times, most recently from f3f83bc to 3bc8ea9 Compare August 3, 2023 09:57
Similar to the existing 3D CPUParticles physics interpolation.
// Now, if we are interpolating, we want to force a single tick update.
// If we don't do this, it may be an entire tick before the first update happens.
if (_interpolated) {
_update_internal(true);
Copy link
Member Author

@lawnjelly lawnjelly Aug 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The delta for the priming here could possibly be tweaked, depending on feedback from users. This assumes the particle system is entering the tree on a physics tick, and won't get an update till the next physics tick.

If it enters on a frame rather than tick, there could be a slight inconsistency, and we could possibly detect this and use the physics_interpolation_fraction to estimate a sensible delta.

But this would be fine for a follow up PR based on feedback.

@lawnjelly lawnjelly marked this pull request as ready for review August 3, 2023 16:14
@lawnjelly lawnjelly requested review from a team as code owners August 3, 2023 16:14
@lawnjelly
Copy link
Member Author

lawnjelly commented Aug 3, 2023

Marking as ready for review, could do with further testing. It seems fine in my tests so far with jetpaca, testbeds, and Calinou's "platshoot", demos dodge the creeps, physics platformer.

If we could get this in before the next beta that would be great as even if not perfect, it allows users to start making interpolated 2D games. Without this, there is no easy way for them to use particle systems interpolated.

Copy link
Member

@Calinou Calinou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave this a try in https://github.com/Calinou/platshoot/tree/physics-interpolation-test and https://github.com/Calinou/escape-space/tree/physics-interpolation-test and it works as expected in both.

Particles for the player's jetpack in Platshoot don't look very smooth in motion, but particles in Escape Space look very smooth (with the exception of subtick movement which is currently missing, as noted in the PR description).

Either way, I think this is an improvement over what we have already.

@lawnjelly
Copy link
Member Author

lawnjelly commented Aug 4, 2023

Particles for the player's jetpack in Platshoot don't look very smooth in motion, but particles in Escape Space look very smooth (with the exception of subtick movement which is currently missing, as noted in the PR description).

I didn't realise there was a jetpack in Platshoot 😄 , just was trying that, doesn't seem too bad. Likely they look flakey due to "streaking" not being implemented yet (so they come out in clumps on each tick). When I up the ticks per second to 30 they look fine. I'm sure I'll be tweaking the CPUParticles for a while yet, but I'm keen to get a working version in for the beta.

The "priming" behaviour in particular I'm currently tuning, but it's an enhancement and shouldn't prevent merging as is.

UPDATE:
Priming seems fine in my tests so far, so I'll wait for feedback from beta before changing anything else there.

@akien-mga akien-mga merged commit b8ff619 into godotengine:3.x Aug 8, 2023
13 checks passed
@akien-mga
Copy link
Member

Thanks!

@lawnjelly lawnjelly deleted the fti_2d_particles branch August 8, 2023 12:51
@akien-mga akien-mga changed the title [3.x] Physics Interpolation - add support for CPUParticles2D [3.x] Physics Interpolation: Add support for CPUParticles2D Aug 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants