-
-
Notifications
You must be signed in to change notification settings - Fork 21.1k
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
Conversation
e5e0a74
to
0119b24
Compare
@@ -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; |
There was a problem hiding this comment.
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.
f3f83bc
to
3bc8ea9
Compare
Similar to the existing 3D CPUParticles physics interpolation.
3bc8ea9
to
a117a33
Compare
// 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); |
There was a problem hiding this comment.
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.
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. |
There was a problem hiding this 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.
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: |
Thanks! |
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
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.
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 theVisualServer
, we have the option to fix y-sort for global 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.)