From cbfb7bd613a697503fe046428b0fd0fc08829926 Mon Sep 17 00:00:00 2001 From: JFonS Date: Tue, 13 Nov 2018 18:19:16 +0100 Subject: [PATCH] Make 2D particles work OOTB (again) --- drivers/gles3/rasterizer_canvas_gles3.cpp | 4 ++++ drivers/gles3/shaders/canvas.glsl | 5 ++++ scene/2d/canvas_item.cpp | 2 -- scene/2d/cpu_particles_2d.cpp | 28 +++++++++++++++------- scene/2d/cpu_particles_2d.h | 11 +-------- scene/2d/particles_2d.cpp | 14 +++++++++++ scene/3d/cpu_particles.cpp | 29 +++++++++++++++++++++++ scene/3d/particles.cpp | 24 ++++++++++++++++++- 8 files changed, 95 insertions(+), 22 deletions(-) diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 0c6893d41985..6e7ecee007ec 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -967,6 +967,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur //enable instancing state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, true); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, true); state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, true); //reset shader and force rebind state.using_texture_rect = true; @@ -977,6 +978,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur if (texture) { Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); + } else { + state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, Vector2(1.0, 1.0)); } if (!particles->use_local_coords) { @@ -1066,6 +1069,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur glBindVertexArray(0); state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, false); state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false); state.using_texture_rect = true; _set_texture_rect_mode(false); diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 52746e0862f8..ef2319c332f4 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -138,6 +138,11 @@ void main() { highp vec4 outvec = vec4(vertex, 0.0, 1.0); #endif +#ifdef USE_PARTICLES + //scale by texture size + outvec.xy /= color_texpixel_size; +#endif + #define extra_matrix extra_matrix_instance { diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 7c734d6af594..26ad3d0cdd00 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -123,8 +123,6 @@ void CanvasItemMaterial::_update_shader() { code += "\tfloat h_frames = float(particles_anim_h_frames);\n"; code += "\tfloat v_frames = float(particles_anim_v_frames);\n"; - code += "\tVERTEX.xy /= TEXTURE_PIXEL_SIZE * vec2(h_frames, v_frames);\n"; - code += "\tint total_frames = particles_anim_h_frames * particles_anim_v_frames;\n"; code += "\tint frame = int(float(total_frames) * INSTANCE_CUSTOM.z);\n"; code += "\tif (particles_anim_loop) {\n"; diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index bc2bd9a1c5c7..a1b624a246e8 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -153,13 +153,19 @@ CPUParticles2D::DrawOrder CPUParticles2D::get_draw_order() const { return draw_order; } -void CPUParticles2D::_generate_mesh_texture() { +void CPUParticles2D::_update_mesh_texture() { + Size2 tex_size; + if (texture.is_valid()) { + tex_size = texture->get_size(); + } else { + tex_size = Size2(1, 1); + } PoolVector vertices; - vertices.push_back(Vector2(-0.5, -0.5)); - vertices.push_back(Vector2(0.5, -0.5)); - vertices.push_back(Vector2(0.5, 0.5)); - vertices.push_back(Vector2(-0.5, 0.5)); + vertices.push_back(-tex_size * 0.5); + vertices.push_back(-tex_size * 0.5 + Vector2(tex_size.x, 0)); + vertices.push_back(-tex_size * 0.5 + Vector2(tex_size.x, tex_size.y)); + vertices.push_back(-tex_size * 0.5 + Vector2(0, tex_size.y)); PoolVector uvs; uvs.push_back(Vector2(0, 0)); uvs.push_back(Vector2(1, 0)); @@ -193,6 +199,7 @@ void CPUParticles2D::set_texture(const Ref &p_texture) { texture = p_texture; update(); + _update_mesh_texture(); } Ref CPUParticles2D::get_texture() const { @@ -234,9 +241,12 @@ String CPUParticles2D::get_configuration_warning() const { CanvasItemMaterial *mat = Object::cast_to(get_material().ptr()); if (get_material().is_null() || (mat && !mat->get_particles_animation())) { - if (warnings != String()) - warnings += "\n"; - warnings += "- " + TTR("CPUParticles2D animation requires the usage of a CanvasItemMaterial with \"Particles Animation\" enabled."); + if (get_param(PARAM_ANIM_SPEED) != 0.0 || get_param(PARAM_ANIM_OFFSET) != 0.0 || + get_param_curve(PARAM_ANIM_SPEED).is_valid() || get_param_curve(PARAM_ANIM_OFFSET).is_valid()) { + if (warnings != String()) + warnings += "\n"; + warnings += "- " + TTR("CPUParticles2D animation requires the usage of a CanvasItemMaterial with \"Particles Animation\" enabled."); + } } return warnings; @@ -1396,7 +1406,7 @@ CPUParticles2D::CPUParticles2D() { update_mutex = Mutex::create(); #endif - _generate_mesh_texture(); + _update_mesh_texture(); } CPUParticles2D::~CPUParticles2D() { diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h index 15b7642b5e23..d967c3be2669 100644 --- a/scene/2d/cpu_particles_2d.h +++ b/scene/2d/cpu_particles_2d.h @@ -177,7 +177,7 @@ class CPUParticles2D : public Node2D { void _update_render_thread(); - void _generate_mesh_texture(); + void _update_mesh_texture(); protected: static void _bind_methods(); @@ -222,15 +222,6 @@ class CPUParticles2D : public Node2D { void set_texture(const Ref &p_texture); Ref get_texture() const; - void set_h_frames(int p_frames); - int get_h_frames(); - - void set_v_frames(int p_frames); - int get_v_frames(); - - void set_loop_animation(bool p_loop); - bool get_loop_animation() const; - void set_normalmap(const Ref &p_normalmap); Ref get_normalmap() const; diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp index 9c01d81c118d..35b7e7da3ed1 100644 --- a/scene/2d/particles_2d.cpp +++ b/scene/2d/particles_2d.cpp @@ -219,6 +219,20 @@ String Particles2D::get_configuration_warning() const { if (warnings != String()) warnings += "\n"; warnings += "- " + TTR("A material to process the particles is not assigned, so no behavior is imprinted."); + } else { + + CanvasItemMaterial *mat = Object::cast_to(get_material().ptr()); + + if (get_material().is_null() || (mat && !mat->get_particles_animation())) { + const ParticlesMaterial *process = Object::cast_to(process_material.ptr()); + if (process && + (process->get_param(ParticlesMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param(ParticlesMaterial::PARAM_ANIM_OFFSET) != 0.0 || + process->get_param_texture(ParticlesMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_OFFSET).is_valid())) { + if (warnings != String()) + warnings += "\n"; + warnings += "- " + TTR("Particles2D animation requires the usage of a CanvasItemMaterial with \"Particles Animation\" enabled."); + } + } } return warnings; diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp index 5b3229e93104..a22708ac99bb 100644 --- a/scene/3d/cpu_particles.cpp +++ b/scene/3d/cpu_particles.cpp @@ -198,6 +198,35 @@ String CPUParticles::get_configuration_warning() const { String warnings; + bool mesh_found = false; + bool anim_material_found = false; + + if (get_mesh().is_valid()) { + mesh_found = true; + for (int j = 0; j < get_mesh()->get_surface_count(); j++) { + anim_material_found = Object::cast_to(get_mesh()->surface_get_material(j).ptr()) != NULL; + SpatialMaterial *spat = Object::cast_to(get_mesh()->surface_get_material(j).ptr()); + anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == SpatialMaterial::BILLBOARD_PARTICLES); + } + } + + anim_material_found = anim_material_found || Object::cast_to(get_material_override().ptr()) != NULL; + SpatialMaterial *spat = Object::cast_to(get_material_override().ptr()); + anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == SpatialMaterial::BILLBOARD_PARTICLES); + + if (!mesh_found) { + if (warnings != String()) + warnings += "\n"; + warnings += "- " + TTR("Nothing is visible because no mesh has not been assigned."); + } + + if (!anim_material_found && (get_param(PARAM_ANIM_SPEED) != 0.0 || get_param(PARAM_ANIM_OFFSET) != 0.0 || + get_param_curve(PARAM_ANIM_SPEED).is_valid() || get_param_curve(PARAM_ANIM_OFFSET).is_valid())) { + if (warnings != String()) + warnings += "\n"; + warnings += "- " + TTR("CPUParticles animation requires the usage of a SpatialMaterial with \"Billboard Particles\" enabled."); + } + return warnings; } diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp index 10b26778ef85..3fff42aa7822 100644 --- a/scene/3d/particles.cpp +++ b/scene/3d/particles.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "particles.h" +#include "scene/resources/particles_material.h" #include "servers/visual_server.h" @@ -226,15 +227,27 @@ String Particles::get_configuration_warning() const { String warnings; bool meshes_found = false; + bool anim_material_found = false; for (int i = 0; i < draw_passes.size(); i++) { if (draw_passes[i].is_valid()) { meshes_found = true; - break; + for (int j = 0; j < draw_passes[i]->get_surface_count(); j++) { + anim_material_found = Object::cast_to(draw_passes[i]->surface_get_material(j).ptr()) != NULL; + SpatialMaterial *spat = Object::cast_to(draw_passes[i]->surface_get_material(j).ptr()); + anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == SpatialMaterial::BILLBOARD_PARTICLES); + } + if (meshes_found && anim_material_found) break; } } + anim_material_found = anim_material_found || Object::cast_to(get_material_override().ptr()) != NULL; + SpatialMaterial *spat = Object::cast_to(get_material_override().ptr()); + anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == SpatialMaterial::BILLBOARD_PARTICLES); + if (!meshes_found) { + if (warnings != String()) + warnings += "\n"; warnings += "- " + TTR("Nothing is visible because meshes have not been assigned to draw passes."); } @@ -242,6 +255,15 @@ String Particles::get_configuration_warning() const { if (warnings != String()) warnings += "\n"; warnings += "- " + TTR("A material to process the particles is not assigned, so no behavior is imprinted."); + } else { + const ParticlesMaterial *process = Object::cast_to(process_material.ptr()); + if (!anim_material_found && process && + (process->get_param(ParticlesMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param(ParticlesMaterial::PARAM_ANIM_OFFSET) != 0.0 || + process->get_param_texture(ParticlesMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_OFFSET).is_valid())) { + if (warnings != String()) + warnings += "\n"; + warnings += "- " + TTR("Particles animation requires the usage of a SpatialMaterial with \"Billboard Particles\" enabled."); + } } return warnings;