-
-
Notifications
You must be signed in to change notification settings - Fork 21.3k
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] Add half frame to floor() for animated particles UV #53233
[3.x] Add half frame to floor() for animated particles UV #53233
Conversation
Thanks for opening a pull request 🙂 Pull requests should be opened against the Please keep this PR open as the fix is also relevant for |
Sorry for that! Here is the PR on master: #53237 |
I am a little skeptical. Adding 0.5 before calling My guess is that #36435 is actually an issue with how |
I think in this case it works out. The |
I also think it looks good. I'm wondering if it is also susceptible to a similar bug for the x? Should we make a similar adjustment for the x? |
@clayjohn Thanks for your feedback. I understand your point but please note the brackets I added in my changes. As @JFonS pointed out the 0.5 is added before division to add a margin to the floor that is exactly a half frame. Let's assume we have a texture with 3x2 frames. Here is what happens: |
Well for example, if you had e.g. 31.9999999 coming in, with a row of 16. Because of the mod operation, this will come out as 15.9999, instead of 0.0. I only say this because we not long ago had a similar bug in another area of Godot (I forgot the details). Essentially |
@@ -148,7 +148,7 @@ void CanvasItemMaterial::_update_shader() { | |||
code += "\t\tparticle_frame = mod(particle_frame, particle_total_frames);\n"; | |||
code += "\t}"; | |||
code += "\tUV /= vec2(h_frames, v_frames);\n"; | |||
code += "\tUV += vec2(mod(particle_frame, h_frames) / h_frames, floor(particle_frame / h_frames) / v_frames);\n"; | |||
code += "\tUV += vec2(mod(particle_frame, h_frames) / h_frames, floor((particle_frame + 0.5) / h_frames) / v_frames);\n"; |
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 guess to address @lawnjelly's comment this should be:
code += "\tUV += vec2(mod(particle_frame, h_frames) / h_frames, floor((particle_frame + 0.5) / h_frames) / v_frames);\n"; | |
code += "\tUV += vec2(mod(floor(particle_frame + 0.5), h_frames) / h_frames, floor((particle_frame + 0.5) / h_frames) / v_frames);\n"; |
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.
But then this might be worth doing further up when particle_frame
is calculated?
Maybe there's a better operation that could be done on integer values to calculate particle_frame
in the first place instead of using floating point?
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.
It's kind of hard to read and follow in the stringifyed format 😕 but I think it could be:
floor (mod(particle_frame+0.5, h_frames)) / h_frames
Or do the particle_frame += 0.5;
earlier as a once off as @akien-mga points out.
You could also in theory do something like a:
particle_frame = round(particle_frame) + epsilon;
And then not need the later bodges .. but for being a little more 'clever' this is something that would be be bound to screw up on some hardware with some special precision etc.
GLES has next to no support for integers unfortunately, which makes this kind of juggling super annoying but necessary.
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.
Am approving this because, despite my comment about the x coordinate, the PR as is fixes a bug, and there's no reason why we can't do the x in a separate PR after this is merged.
Thanks! |
Depending on the hardware or drivers it can occur on some devices that animated sprites do not render in the correct order. This happens because of an inprecision when calling floor(). Adding a 0.5 before using floor fixes this bug.
Closes #36435