-
-
Notifications
You must be signed in to change notification settings - Fork 21k
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
Implement blending in particle flipbook animation #50442
base: master
Are you sure you want to change the base?
Conversation
3f22211
to
8643ba7
Compare
8643ba7
to
b223d39
Compare
Will you be adding this to CPUParticles3D in this PR or a separate PR? |
It already works with CPUParticles3D – I just tested it 🙂 That said, what do you think about the conditional-vs-shader version issue?
|
This makes changes between frames look smoother, making flipbook particle animation more viable for realistic particle effects such as fire.
b223d39
to
cce713e
Compare
Of course! Because this is in the StandardMaterial code, not in the ParticlesMaterial code.
I think we probably should do another shader version. In theory it should be slightly faster and in practice I find that it is nicer to have as little as possible in the generated code when a user selects "Convert to StandardMaterial3D". I don't have a strong preference though, the performance impact is probably balanced out by the pain of having another shader permutation. edit: it could even be done like below where there is a shader permutation for particles_animation. That way the extra cost is only there for animated particles
You will have to add a fragment function when using animation blending. It shouldn't be too hard, as you are just inserting the string of characters, the same as in 3D. You add it all here: godot/scene/main/canvas_item.cpp Lines 128 to 150 in cce713e
|
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.
Actually, this is also going to break if force_srgb
is used or use_vertex_colors
is enabled.
Probably what you should do is add something like the following at line 1003:
if (particles_anim_blend) {
albedo_tex = mix(albedo_tex, texture(texture_albedo, particles_anim_next_frame_uv_coord), particles_anim_next_frame_mix);
}
This would allow you to delete the two conditions when assigned ALBEDO and ALPHA and would allow it to automatically use SRGB and COLOR as appropriate.
code += "\tif (particles_anim_blend) {\n"; | ||
code += "\t\tALBEDO = albedo.rgb * mix(albedo_tex.rgb, texture(texture_albedo, particles_anim_next_frame_uv_coord).rgb, particles_anim_next_frame_mix);\n"; | ||
code += "\t} else {\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.
You should read and store the albedo_blend_tex
here. This will allow you to only read the texture once. Below when reading alpha, you can just use albedo_blend_tex.a
.
code += "\tif (particles_anim_blend) {\n"; | |
code += "\t\tALBEDO = albedo.rgb * mix(albedo_tex.rgb, texture(texture_albedo, particles_anim_next_frame_uv_coord).rgb, particles_anim_next_frame_mix);\n"; | |
code += "\t} else {\n"; | |
code += "\tvec4 albedo_blend_tex = vec4(1.0);\n"; | |
code += "\tif (particles_anim_blend) {\n"; | |
code += "\t\talbedo_blend_tex = texture(texture_albedo, particles_anim_next_frame_uv_coord);\n"; | |
code += "\t\tALBEDO = albedo.rgb * mix(albedo_tex.rgb, albedo_blend_tex.rgb, particles_anim_next_frame_mix);\n"; | |
code += "\t} else {\n"; |
@@ -1084,7 +1113,11 @@ void BaseMaterial3D::_update_shader() { | |||
code += "\tALPHA = 1.0;\n"; | |||
|
|||
} else if (transparency != TRANSPARENCY_DISABLED || flags[FLAG_USE_SHADOW_TO_OPACITY] || (distance_fade == DISTANCE_FADE_PIXEL_ALPHA) || proximity_fade_enabled) { | |||
code += "\tif (particles_anim_blend) {\n"; | |||
code += "\t\tALPHA = albedo.a * mix(albedo_tex.a, texture(texture_albedo, particles_anim_next_frame_uv_coord).a, particles_anim_next_frame_mix);\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.
code += "\t\tALPHA = albedo.a * mix(albedo_tex.a, texture(texture_albedo, particles_anim_next_frame_uv_coord).a, particles_anim_next_frame_mix);\n"; | |
code += "\t\tALPHA = albedo.a * mix(albedo_tex.a, albedo_blend_tex.a, particles_anim_next_frame_mix);\n"; |
@clayjohn Thanks for the review! I tried implementing your changes locally, but unfortunately, it worsened the overall blending. It's possible that I've applied them incorrectly, so I included the diff below (relative to the PR's current state) for reference. These were my local changes so far: diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 6f987602e2..b36539a322 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -1001,6 +1001,10 @@ void BaseMaterial3D::_update_shader() {
}
}
+ code += "\tif (particles_anim_blend) {\n";
+ code += "\t\talbedo_tex = mix(albedo_tex, texture(texture_albedo, particles_anim_next_frame_uv_coord), particles_anim_next_frame_mix);\n";
+ code += "\t}\n";
+
if (flags[FLAG_ALBEDO_TEXTURE_FORCE_SRGB]) {
code += "\talbedo_tex.rgb = mix(pow((albedo_tex.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)),vec3(2.4)),albedo_tex.rgb.rgb * (1.0 / 12.92),lessThan(albedo_tex.rgb,vec3(0.04045)));\n";
}
@@ -1010,8 +1014,10 @@ void BaseMaterial3D::_update_shader() {
}
// Use particle flipbook animation if specified.
+ code += "\tvec4 albedo_blend_tex = vec4(1.0);\n";
code += "\tif (particles_anim_blend) {\n";
- code += "\t\tALBEDO = albedo.rgb * mix(albedo_tex.rgb, texture(texture_albedo, particles_anim_next_frame_uv_coord).rgb, particles_anim_next_frame_mix);\n";
+ code += "\t\talbedo_blend_tex = texture(texture_albedo, particles_anim_next_frame_uv_coord);\n";
+ code += "\t\tALBEDO = albedo.rgb * mix(albedo_tex.rgb, albedo_blend_tex.rgb, particles_anim_next_frame_mix);\n";
code += "\t} else {\n";
code += "\t\tALBEDO = albedo.rgb * albedo_tex.rgb;\n";
code += "\t}\n";
@@ -1114,7 +1120,7 @@ void BaseMaterial3D::_update_shader() {
} else if (transparency != TRANSPARENCY_DISABLED || flags[FLAG_USE_SHADOW_TO_OPACITY] || (distance_fade == DISTANCE_FADE_PIXEL_ALPHA) || proximity_fade_enabled) {
code += "\tif (particles_anim_blend) {\n";
- code += "\t\tALPHA = albedo.a * mix(albedo_tex.a, texture(texture_albedo, particles_anim_next_frame_uv_coord).a, particles_anim_next_frame_mix);\n";
+ code += "\t\tALPHA = albedo.a * mix(albedo_tex.a, albedo_blend_tex.a, particles_anim_next_frame_mix);\n";
code += "\t} else {\n";
code += "\tALPHA = albedo.a * albedo_tex.a;\n";
code += "\t}\n"; On the videos below, look at the number 4 fading in and out. Before, it faded in and out properly, but it no longer does. (The animation is marked to loop.) Beforenumbers_blending_before.mp4Afternumbers_blending_after.mp4 |
I see the mistake, you added both alternatives that I mentioned. Sorry that review was confusing. I proposed two alternative ways of doing the same thing. All you need is the top 4 changed lines in your diff.
|
Is this change optional? i.e. can it be opted out of by game devs? |
Yes; it's disabled by default. |
This makes changes between frames look smoother, making flipbook particle animation more viable for realistic particle effects such as fire.
This works with both GPUParticles3D and CPUParticles3D.
This closes godotengine/godot-proposals#1636.
Testing project: test_particle_animation.zip (
master
only, won't work in3.x
)Preview
particle_flipbook_blend.mp4
TODO