Browse Source

Make 2D particles work OOTB (again)

JFonS 6 years ago
parent
commit
cbfb7bd613

+ 4 - 0
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);

+ 5 - 0
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
 
 	{

+ 0 - 2
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";

+ 19 - 9
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<Vector2> 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<Vector2> uvs;
 	uvs.push_back(Vector2(0, 0));
 	uvs.push_back(Vector2(1, 0));
@@ -193,6 +199,7 @@ void CPUParticles2D::set_texture(const Ref<Texture> &p_texture) {
 
 	texture = p_texture;
 	update();
+	_update_mesh_texture();
 }
 
 Ref<Texture> CPUParticles2D::get_texture() const {
@@ -234,9 +241,12 @@ String CPUParticles2D::get_configuration_warning() const {
 	CanvasItemMaterial *mat = Object::cast_to<CanvasItemMaterial>(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() {

+ 1 - 10
scene/2d/cpu_particles_2d.h

@@ -177,7 +177,7 @@ private:
 
 	void _update_render_thread();
 
-	void _generate_mesh_texture();
+	void _update_mesh_texture();
 
 protected:
 	static void _bind_methods();
@@ -222,15 +222,6 @@ public:
 	void set_texture(const Ref<Texture> &p_texture);
 	Ref<Texture> 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<Texture> &p_normalmap);
 	Ref<Texture> get_normalmap() const;
 

+ 14 - 0
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<CanvasItemMaterial>(get_material().ptr());
+
+		if (get_material().is_null() || (mat && !mat->get_particles_animation())) {
+			const ParticlesMaterial *process = Object::cast_to<ParticlesMaterial>(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;

+ 29 - 0
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<ShaderMaterial>(get_mesh()->surface_get_material(j).ptr()) != NULL;
+			SpatialMaterial *spat = Object::cast_to<SpatialMaterial>(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<ShaderMaterial>(get_material_override().ptr()) != NULL;
+	SpatialMaterial *spat = Object::cast_to<SpatialMaterial>(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;
 }
 

+ 23 - 1
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<ShaderMaterial>(draw_passes[i]->surface_get_material(j).ptr()) != NULL;
+				SpatialMaterial *spat = Object::cast_to<SpatialMaterial>(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<ShaderMaterial>(get_material_override().ptr()) != NULL;
+	SpatialMaterial *spat = Object::cast_to<SpatialMaterial>(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<ParticlesMaterial>(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;